Hiding rows by using a criteria on specific cells is too slow - vba

I am new to VBA, I have a requirement where I have a sheet of data containing more than 5000 rows. Rows might increase and decrease so it is not a fixed value. Now I have 20 columns and I have a user input cell where he will enter say in cell A3 5 and cell A5 is 9.
What I need to do is filter row wise, matching values in the range and hide them. The complication is that the matching value has to look on only 5 out of 20 columns. When any one of the cell values matches from the 5 columns, then I should not hide the rows and the rest should be hidden.
example:
A B C D E F G H I J
2014.Jan 2014.FEB 2014.MAR
value1 value2 value3 value1 value2 value3 value1 value2 value3
Material1 5 10 15 20 25 30 35 40 45
Material2 7 8 9 10 11 12 13 14 15
Material3 2 3 4 5 6 7 8 9 10
When user enter value 0 to 9.
Then I need to check the columns D,G,J and check if the number falls between 0 to 9. If any one
matches then don't hide the row.
The output should be:
A B C D E F G H I J
2014.Jan 2014.FEB 2014.MAR
value1 value2 value3 value1 value2 value3 value1 value2 value3
Material2 7 8 9 10 11 12 13 14 15
Material3 2 3 4 5 6 7 8 9 10
I tried the code below as a sample of the solution but it takes a long time as it loops each field.
Application.EnableEvents = False
LastRow = Cells(Cells.Rows.Count, "H").End(xlUp).Row
On Error Resume Next
For Each c In Range("M21:M" & LastRow)
If c.value >= Range("L10").value And c.value <= Range("N10").value Then
c.EntireRow.Hidden = True
Else
c.EntireRow.Hidden = False
End If
Next
On Error GoTo 0
Application.EnableEvents = True
Is there a better way to do it?

Related

How do I merge multiple xls files into one dataframe in python?

I have excel files which each have 3 sheets and all same column headers.
I want to merge all so that I get one combined dataframe. This dataframe should have the sheetname,row number and xls filename listed next to the final dataframe.
i tried
import pandas as pd
dfe = pd.concat(pd.read_excel('abc1.xls', sheet_name=None), ignore_index=True)
this combined all sheets for one of the files but did not write the row numbers or sheetnames next to the data. How can I do the same?
Desired output-
Rownumber Sheetname Filename State Region Brand
1 tig abc1.xls CA S Go
2 con abc2.xls IA A Po
Here's how to do it. I used two functions. The first function reads all sheets within a single Excel file, and adds the sheet name. The second function takes all of the excel files, and uses the first function to read all the sheets in all the files.
from pandas import pd
def read_sheets(filename):
result = []
sheets = pd.read_excel(filename, sheet_name=None)
for name, sheet in sheets.items():
sheet['Sheetname'] = name
sheet['Row'] = sheet.index
result.append(sheet)
return pd.concat(result, ignore_index=True)
def read_files(filenames):
result = []
for filename in filenames:
file = read_sheets(filename)
file['Filename'] = filename
result.append(file)
return pd.concat(result, ignore_index=True)
You can call this by providing a list of files to read:
files = ['multisheet.xls', 'multisheet2.xls']
read_files(files)
For the example I tried it on, it produces a dataframe like this:
A B A+B Sheetname Row Filename
0 1 10 11 Sheet1 0 multisheet.xls
1 2 11 13 Sheet1 1 multisheet.xls
2 3 12 15 Sheet1 2 multisheet.xls
3 4 13 17 Sheet1 3 multisheet.xls
4 3 10 13 Sheet2 0 multisheet.xls
5 3 11 14 Sheet2 1 multisheet.xls
6 3 12 15 Sheet2 2 multisheet.xls
7 3 13 16 Sheet2 3 multisheet.xls
8 1 10 11 Sheet1 0 multisheet2.xls
9 2 11 13 Sheet1 1 multisheet2.xls
10 3 12 15 Sheet1 2 multisheet2.xls
11 4 13 17 Sheet1 3 multisheet2.xls
12 4 10 13 Sheet2 0 multisheet2.xls
13 3 11 14 Sheet2 1 multisheet2.xls
14 3 12 15 Sheet2 2 multisheet2.xls
15 3 13 16 Sheet2 3 multisheet2.xls

How to make one column match duplicates in another column

This problem is out of my ability range and I can’t get anywhere with it beyond knowing I can probably use LEAD, LAG or maybe a cursor?
Here is a breakdown of the table and question:
row_id is always an IDENTITY(1, 1) column.
The set_id column always starts out in groups of 3s (two 0s for the first set_id, don't worry about why).
The letter column is alphabetic. There are varying counts of duplicates.
Here's the original table:
row_id
set_id
letter
1
0
A
2
0
A
3
1
A
4
1
B
5
1
B
6
2
B
7
2
B
8
2
C
9
3
C
10
3
C
11
3
D
12
4
D
13
4
D
14
4
D
What I need is a code that: if there is a duplicate letter in the next row, then the set_id in the next row should be the same as the previous row (alt_set_id).
If that doesn't make sense, here is the result I want:
row_id
set_id
letter
alt_set_id
1
0
A
0
2
0
A
0
3
1
A
0
4
1
B
1
5
1
B
1
6
2
B
1
7
2
B
1
8
2
C
2
9
3
C
2
10
3
C
2
11
3
D
3
12
4
D
3
13
4
D
3
14
4
D
3
Here's where I am with code so far, I'm not really close but I think I am on the right path:
SELECT
*,
CASE
WHEN letter = [letter in next row]
THEN 'yes'
ELSE 'no'
END AS 'next row a duplicate?',
'tbd' AS alt_row_id
FROM
(SELECT
*,
LEAD(letter) OVER (ORDER BY row_id) AS 'letter in next row'
FROM
sort_test) AS dt
WHERE
row_id = row_id
That query has the below result set, which is something I think I can work with, but it doesn't feel very efficient and I'm not yet getting the result needed in the alt_set_id column:
row_id
set_id
letter
letter in next row
next row a duplicate?
alt_set_id
1
0
A
A
yes
tbd
2
0
A
A
yes
tbd
3
1
A
B
no
tbd
4
1
B
B
yes
tbd
5
1
B
B
yes
tbd
6
2
B
B
yes
tbd
7
2
B
C
no
tbd
8
2
C
C
yes
tbd
9
3
C
C
yes
tbd
10
3
C
D
no
tbd
11
3
D
D
yes
tbd
12
4
D
D
yes
tbd
13
4
D
D
yes
tbd
14
4
D
NULL
no
tbd
Thanks for any help!
Based on your example data, you want the minimum set_id for each letter. If so, use window functions;
select t.*, min(set_id) over (partition by letter) as alt_set_id
from sort_test t;
It would appear if I understand correctly a simple correlated subquery will give you the desired result:
select *, (select Min(set_Id) from t t2 where t2.letter=t.letter) as alt_set_id
from t
See working DB Fiddle

Pandas Dataframe Checking Consecutive Values in a colum

Have a Pandas Dataframe like below.
EventOccurrence Month
1 4
1 5
1 6
1 9
1 10
1 12
Need to add a identifier column to above panda's dataframe such that whenever Month is consecutive thrice a value of True is filled, else false. Explored few options like shift and window without luck. Any pointer is appreciated.
EventOccurrence Month Flag
1 4 F
1 5 F
1 6 T
1 9 F
1 10 F
1 12 F
Thank You.
You can check whether the diff between rows is one, and the diff shifted by 1 is one as well:
df['Flag'] = (df.Month.diff() == 1) & (df.Month.diff().shift() == 1)
EventOccurrence Month Flag
0 1 4 False
1 1 5 False
2 1 6 True
3 1 9 False
4 1 10 False
5 1 12 False
Note that this will also return True if it is consecutive > 3 times, but that behaviour wasn't specified in the question so I'll assume it's OK
If it needs to only flag the third one, and not for example the fourth consecutive instance, you could add a condition:
df['Flag'] = (df.Month.diff() == 1) & (df.Month.diff().shift() == 1) & (df.Month.diff().shift(2) !=1)

Excel formula or VBA searching for matching values, every matching value found move to new column

I'm new to excel and have very basic knowledge of it. I hope that some one will by able to help me as I'm trying to find similar formula or VBA code for few days now and no luck.
I need formula or VBA to find same value in range and when first matching value find move to new column.
For example:
Value in A1 check against all values in column H and if same value found move that value to B1, then again value in A1 check against values left in H column if same found move to C1, every time finds A1 same as value in H column moves that value to new column D1, E1 .....continue until all values in H column have been checked and matching ones moved. After this value in A2 checked against all values in H column and all matching values moved to B2,C2,E2 etc. Continue until all values have been moved from column H.
This how data looks before moving:
0 A B C D E F G H
----------------------------------------------------------
1 123 123
2 256 123
3 333 123
4 123
5 123
6 256
7 256
8 333
9 333
10 333
11 333
12 333
13 333
After movment:
0 A B C D E F G H
----------------------------------------------------------
1 123 123 123 123 123 123
2 256 256 256
3 333 333 333 333 333 333 333
4
5
6
7
8
9
10
11
Something like this:-
Sub tester()
With ActiveSheet
For Each cell In .Range("A1:" & .Range("A1").End(xlDown).Address)
i = 1
For Each c In .Range("H1:" & .Range("H1").End(xlDown).Address)
If cell.Value = c.Value Then
cell.Offset(0, i).Value = c.Value
i = i + 1
End If
Next
Next
End With
End Sub
Note: This does not clear the results from run to run.

macro to re-arrange data

I have been trying to write a macro to re-arrange the Cells in the rows and columns of Stock tables for the output I desire. Luckily the Stock Tables are generally the same each and every time (Different names and values), and the desired outcome is the same format..
Here is some example Data.
A
1 Name
2 description
3 description
4 description
5 description
6 ID#: 56284
7 Quantity in stock: 34
8 Zoom In and Configure
B
1 Name
2 description
3 description
4 description
5 description
6 ID#: 56284
7 Quantity in stock: 50
8 Zoom In and Configure
And I would like the Output to go into something like this(If possible to sheet2 starting on Cell B2):
B C E
B Being Row 1
C being Row 2 3 4 and 5 Combined
E being JUST Row 7 Stock Value I.E 50
On a single spreadsheet there would be 4 columns, and 8 rows I would have to re-arrange.. Making 32 total.
It would be great to automated this, so any help would be greatly appreciated.
Let me clarify my understanding. For each column you want the following data format:
A A
1 Name 1 Name
2 Desc1 2 Desc1; Desc2; Desc3; Desc4
3 Desc2 On sheet 2 3 50
4 Desc3 --------------->
5 Desc4
6 Id#: 56284
7 Quantity in Stock: 50
8 Zoom in and configure
If this is the case you can use the following code. It assumes your data is in A1 to D8 in Sheet 1.
Sub FormatData()
Dim col As Integer
For col = 1 To 4
With Worksheets(2)
.Cells(1, col) = Cells(1, col) //Get name
.Cells(2, col) = Cells(2, col) & "; " & Cells(3, col) & "; " & Cells(4, col) & "; " & Cells(5, col) //Concatenate descriptions into single string
.Cells(3, col) = Cells(7, col) //Get quantity in stock
End With
Next col
End Sub