Vba select entire colum only used range - vba

Does anyone know how to select entire column but only used cells.
Normally the data is continuous. One issue is that sometimes the sheet is filled only for two rows sometimes for hundreds.
What I need to obtain is to loop for all the files in the folder and copy recognized columns only with data. I cannot have selection of entire column because while pasting one below previous macro will throw an error due to range area not fitting.
The source data begins in different rows. Once it starts in second row the other time in third. There are no headers.

I know this is old, but this is an easy way to select the data in a specific column and move it to a new location. It will remove all blanks in the range.
Columns("E:E").SpecialCells(xlCellTypeConstants).Copy Destination: = ActiveSheet.Range("F1")

MaxRow = Range("E" & Rows.Count).End(xlUp).Row
Range("E1:E" & MaxRow).Select
Where E is your Column

Related

How to merge or add rows based on IF condition while maintaining column row order

I need to merge several sheets and maintain data integrity. I have managed to reduce the problem to the following example and would really appreciate some help. The two columns have to be merged into one. The data in a column has to stay in the order it is originally in as each cell is a code that refers to time data. The duplicates need to be reduced to one entry as the whole data set will later be geo coded and duplicates are not tolerated.
The data is complicated and messy but essentially the problem i cannot solve can be artificially reduced to the following for simplicity:
[edit: Yellow bus stops at the following stop codes in the given order.
Blue bus stops at the following stop codes in the given order.
The order in which the buses stop cannot be changed.
The output is one list including all of the stop codes only once, retaining the order present in both lists.]
I want to change it to this:
The colour coding is just to make it clear to readers here.
The green represents where duplicates have been reduced to one (this will allow me to vlookup the data against the code and enter the data from both sheets in the same row.
The order that the codes are in must be maintained so i think i just have to move all the data down.
So, this is, (conceptually), what i was trying to do as a first stage.
Each row retains the order of data but is spread across enough rows to have enough space for both columns in one. The duplicates take the position of the one which has greater row number.
The rest of the solution follows procedurally. I can then delete duplicate codes, and create a new list with all of the values, then remove the spaces.
So if i can get to there i should be ok.
Therefore, as far as i can tell, i need to match with two formulas:
=MATCH(A1,$B$1:$B$11,0)
=MATCH(B1,$A$1:$A$11,0)
but i am not sure if this is actually the direction to take.
It gives me the row numbers on which the common entries occur, but I am not sure how recreate the necessary positions.
Perhaps i need to create these dummy columns and then count the necessary total rows, but how to do that between errors?
Or, have a dynamic running offset. But not sure how to do that either. I am finding it very difficult to wrap my head around it.
It has occurred to me that each value will be on the row number equal to the number of unique values in the two columns above it.
Many thanks in advance for any pointers / solution.
I have tried to reduce the problem down and make it as clear as possible. If anyone can see the solution and can also see where i need to focus my learning, advice on specific area of training would also be welcome.
Cheers
D
I think your problem is more easily addressed with VBA. Let's assume you are working in columns A and B (meaning, 1st and 2nd columns). In your example you have two columns and 11 rows, and since you want to handle your data row-by-row, row is the outer loop and column is the inner loop:
Sub Indexing()
Dim irow, icol, count As Integer
Dim lookIn, FoundRange As Range
count = 1
For irow = 1 To 11:
For icol = 1 To 2:
Cells(irow, icol).Select
Selection.Copy
Set lookIn = Range("F1:F" & count)
Set FoundRange = lookIn.Find(what:=Cells(irow, icol).Value, lookIn:=xlFormulas, lookat:=xlWhole)
If FoundRange Is Nothing Then
Range("F" & count).Select
ActiveSheet.Paste
count = count + 1
End If
Next icol
Next irow
End Sub
This yields the following result, output in column F:
Note that the order is slightly different from yours, but it sort of makes more sense. In your result example, you have 113 before 68, although the first number to appear in row #4 is 68. There are other differences so maybe I misunderstood the order you wanted.
You can adapt this code as follows:
If you have more columns, just replace the 2 in the icol loop by whatever number of columns you want.
If you have more rows, just replace the 11 in the irow loop by whatever number of rows you want.
If you want this to be written in a different column (not column F, as it is now), just replace F with the column letter that you want.
If you are not familiar with Macros and need help setting this up, let me know.

How to avoid adding a new row to the first row of subtotaled ranges to protect Subtotal formula

I have a Excel sheet, which includes many groups and subgroups. Each subgroup has their own subtotal. And as long as I can't know how many lines users will require for the subgroups, I only left 3 rows blank for each subgroup and created a button which triggers Automatically Copy and Insert Copied Row macro.
Now I need to avoid users to trigger the button while they are on the First and the Last row of any subgroup. (If you copy and insert first row, subtotal formula doesn't recognise the new added line because it will be out of the range and Last row has another specific formulas which I don't want users to copy above)
I've been searching SO and the other Excel blogs for a long time but because of my list is very dynamic and have many different subtotals none of them was suitable to my case.
How can I define all of the first and last rows of my different subtotal ranges (and maybe their Title's rows) to avoid them being copied and then inserted above?
I can imagine 2 ways to do this. When the "New Row" button is pressed check if the current row is a headline/subheadline whatever …
by checking its format (eg specific background color etc).
If Not Worksheets("Sheet1").Range("A" & iRow).Interior.Color = 15004911 Then
'copy that row
End If
or by using an extra helper column that specifies the rows as header rows or non copyable rows. If you don't want the helper column to be seen you can hide it.
If Not Worksheets("Sheet1").Range("X" & iRow).Value = "Header" Then
'copy that row
End If
'where X is the helper column
And if it is a headline row then deny the copy process.
One way that doesn't involve programming have your sum range extend into rows that won't change. So you could start the subtotal in the header row (assuming there is no content in the relevant cell in that row). Another way is to have a hidden row at the top and bottom of each sum range and that is included in the sum range. So you would sum rows 10 to 14, but 10 and 14 would be hidden (and empty) and the user would just get shown rows 11, 12 and 13. Adding a new row would push the hidden rows down and extend the subtotal.
Another way is to use the indirect function.
Say your formula was
=SUBTOTAL(9,H7:H10)
If you use indirect for the lower bound, it will always refer to the cell immediately above, regardless of how many rows are added in between.
=SUBTOTAL(9,H7:INDIRECT("H"&ROW()-1))
And taking it one step further, use the upper title row as the anchor to always add up the gap between the title and the subtotal.
=SUBTOTAL(9,INDIRECT("H"&ROW(H6)+1):INDIRECT("H"&ROW()-1))

assigning formula to variable range of rows VBA

I am trying to create a macro which dynamically performs a vlookup for a worksheet w/ a constantly increasing number of rows; I'd like to write the code so that it runs the vlookup from Q2 to the last populated row in col. Q (whatever that may be), and so far I have come up with this:
Range("Q2", Range("Q2").End(xlDown)).Value = "=VLOOKUP(A2,sheet2!A:BO,67,FALSE)"
..The macro performs everything it needs to do & changes accordingly for each row but it also runs infinitely down the column after there is no more data. I wanted to know if there's a way to do this in one line of code if possible. I'm sort of new to VBA & couldn't find an already-posted answer which sufficiently solved my problem so any help would be greatly appreciated.
This should work according to the information you provided. I'm guessing you are replacing an existing value with the formula otherwise the row lookup is going to return a value you don't want. If you want the last row from another column just change the Q in Cells(Rows.Count, "Q").End(xlUp).Row to the column you want.
Range("Q2:Q" & Cells(Rows.Count, "Q").End(xlUp).Row).Value = "=VLOOKUP(A2,sheet2!A:BO,67,FALSE)"

vba excel AdvancedFilter method for a table with dates criteria does not work

first af all i'm glad to enjoy this nice community, this is my first post so apologize me in advance for any mistake i'll do in the post.
I got a table named example generated by importing data from an access file, so the number of rows changes dynamically...I'm trying to apply the AdvancedFilter method to this table via VBA.
I've used the first row of the sheet for copying the header of the table and in the second row i set my parameters for filtering, so in the range A1:D2 i got the criteria. Starting from row 5 i have the table example: it starts with a header row and goes on with all the rows of data, all imported from the access file, for example a range A5:D20.
If i apply the advanced filter manually (click on the advanced filter button and fill the form) specifying the range of the table A5:D30 and the range of the criteria A1:D2 it works fine...but if instead of specifying the range of the data i use the name of the table example the result is different, just one row instead of the five (right) rows i expect...why?!?
Now, if the question above is just for curiosity (but i'm sure it's connected with my problem), the main problem is that i'm trying to do the same thing via VBA code. I tried
Worksheets("name").Range("example[#All]").AdvancedFilter _
Action:=xlFilterInPlace, CriteriaRange:=Range("A1:D2"), Unique:=False
and
Worksheets("name").ListObjects("example").Range.AdvancedFilter _
Action:=xlFilterInPlace, CriteriaRange:=Range("A1:D2")
but both don't work: the filtering action didn't return no lines.
Even if i try
Worksheets("name").Range("A5:D30").AdvancedFilter _
Action:=xlFilterInPlace, CriteriaRange:=Range("A1:D2"), Unique:=False
specifying manually the range (not a solution for my problem because the range changes dynamically, but for test purpose...) the problem persists, the code didn't return no lines.
Note: if i select the range in the codes above instead of AdvancedFilter it the selection is correct: the entire table with the header
The first code is the same automatically written if i start recording a macro, do the filtering manually, and stop recording the macro (code written exactly with the table reference)...the wierd thing is that when i manually do the operation (while recording the macro) it filters correctly, but if i start the macro just recorded...nothing, same as if i run the code written above.
If i open the formula->names tab i can find the example table but the range specifyed is not starting from row 5 but from 6...it's like the header is not considered, don't know why...but it's automatically generated with the importation of the data so i don't know how to change the range keeping the reference to the imported data...maybe is this the issue?!?
Don't know how to solve the problem, please help me :)
Edit:
Two of the criteria i'm using for filter are date criteria, specifically: date <= xx/yy/zzzz and date >= aa/bb/cccc and the problem it's exactly this...if i try the three codes above filtering with a string criteria, they works, if i use them with the dates criteria, they don't. So i guess the problem depends on how VBA hands the dates data types. Any suggestion?
The cells used for criteria contain this formula ("SE" is the italian version of "IF"):
=SE(filtro!F2="";"";">="&filtro!F2)
=SE(filtro!F3="";"";"<="&filtro!F3)
i take the criteria from another sheet ("filtro") and if the cell is filled i report the data inserted with <= or >= for the criteria, otherwise the cell remains empty for don't set any condition.
Thanks
Ettore
Try this below steps. It is working for me.
First we should create a named range (Define Name) (call it is Table),give the range as dynamic using the formula =OFFSET(Sheet1!A5,0,0,COUNTIF(Sheet1!$A$5:$A$100,"<>"),4).
Paste this offset formula while creating the name range - Table.
This formula will changes the range dynamically.
Write VBA code as below
Sub Advanfil()
'
' Advanfilt Macro
'
'
Range("Table").AdvancedFilter Action:=xlFilterInPlace, CriteriaRange:= _
Range("A1:D2"), Unique:=False
End Sub
I think the above should ease ur difficulty.
Ok, finally i fix the issue and whant to share the solution.
As i mentioned in the edit of my question, two criteria of the filter are dates, i found two problems and both are connected with this:
When i imported the data from other source (access file) and populated the table that i was going to filter i did not set the appropriate format to the fields, i left all as excel decided and this was a problem. The correct way is to set:
The fields in the table (the ones with the data to be filtered) as date with a preformatted format (not simple for me because they were stored as text in the access so i must made a SQL string for extract data in the correct type and format).
The field where store the condition for the filter as general (in my case this field contains the formula mentioned int the edit of my question).
The field where i insert the dates for filtering (the one referenced in the formula) as date with the same format as the fields of the table (point 1.).
The formula mentioned in the edit of my question looks at a cell (where i insert the date) and, if this cell is filled, returns something like <=data-inserted or >=data-inserted (and this is OK) BUT when nothing is inserted in the cell returns "". For a string criteria in the filter this is ok, but for a date criteria is not, this causes the filter to don't find nothing with "" in the table fields filled with dates. I tryed to use null value or other similar values but i couldn't find what is nothing for a date criteria...so the workaround i used is to return <=31/12/2100 or >=01/01/1900 when i don't whant to limit the grater or the lower dates.
Hope this could help someone.
Ettore
Fill CRITERIA for null or "" cell in date-formatted field with just an equal sign =
Excel Advanced Filter understands that means BLANK cell

Similar data sets, need to iterate through rows with VBA [duplicate]

This question already has answers here:
Find last used cell in Excel VBA
(14 answers)
Closed 7 years ago.
Title may not make complete sense. But description below should aid. I have similar data sets that come from one of our test machines that are no different unless by the number of samples given to the machine changes.
There is a macro now that assumes 6 samples are to be measured but if more or less than 6 are done, it screws up the selection of data and then we get false numbers.
So I would like to edit it such that the VBA script intelligently iterates through a given range of cells defined by the first cell where the header for data is contained. This ideally returns the position of the last row and then the VBA script has knowledge of where to look for the specific numbers I want. i.e. cell E12 contains the header for the data I'm concerned with, and goes until E?? has no data in that cell
TL;DR - I need help with some code to give me the position of the last row that has data in it, starting from a certain cell.
I would recommend this:
Dim LastRow As Long
With Sheets("Sheet1")
LastRow = .Range("E" & .Rows.Count).End(xlUp).Row
End With
But bare in mind that:
this would start reading cells from the rows count of the sheet and go upwards until it bums into data filled cell only then it would return the index of that row.
this would return the last cell of data based on the column E. So if
you have multiple columns and you're processing data for an entire sheet, make sure to choose that one column with the most
data.
This would yield an error if you there are merged cells in the column.
You can then construct your intelligent data range.
it would be something like:
Dim r As Range
Set r = Range("A1:B" & LastRow)