Adjust criteria to depend on multiple values - vba

I have been working on a code to copy the data from one specific range(always the same) and paste in another spreadsheet always in the row below. So basically, it starts pasting on row 11, but if I run again it will paste on the row 12 and there it goes.. The code has been working fine, but there is only one problem. It identifies the next empty row(to paste) based on the value of the column AP, but i want it to identify based on the values of all the columns between AP:BA. Thus, if there is any value on those cells, it should copy on the row below, not only if there is a value on AP. Does someone know how to change my code in order to solve this problem? Thank You very much
Sub Copy_Shanghai()
Dim count As Integer
count = 11
Do While Worksheets("Time Evolution").Range("AP" & count).Value <> ""
'<>"" means "is not empty", as long as this happens we go down looking for empty cell
count = count + 1
Loop
'Now count is row with first empty cell outside of top 10 rows in column C
Worksheets("Fill").Range("E5:P5").Copy
Worksheets("Time Evolution").Range("AP" & count).PasteSpecial xlPasteValues
End Sub

Related

Excel VBA deleting certain rows with certain conditions

I found a code online which works but I am failing to change it for my purpose. Each entry in my spreadsheet contains different formulas as well as an Iferror function with the aim of making cells with error messages appear as blank. For example lets say a cell E3 is dependent on cell F3 with a certain formula (for clarification lets say F3/2.5). It is obvious if there is no entry in cell F3 then an error message would display in cell E3. For this reason, I use the IFERROR function to display the cell as blank. The difficulty arises when I want to delete blank rows after a click on the macro button. However, since that cell does have an entry (a formula which in turn returns an error message), that cell does not delete. Also I need to run this code over 3 different selection ranges. Please can someone help! The code I found was from a different thread on this forum and is:
`sub foo()
dim r As Range, rows As Long, i As Long
Set r = ActiveSheet.Range("A1:Z50")
rows = r.rows.Count
For i = rows To 1 Step (-1)
If WorksheetFunction.CountA(r.rows(i)) = 0 Then r.rows(i).Delete
Next
End Sub`
Thanks Alot!
EDIT: If statement added to the autofilter as it was deleting a row when there were no blanks
You will want to set up a column in the spreadsheet with the following sumproduct:
=SUMPRODUCT((LEN(A1:F1)>0)*1)
This is calculating how many cells' values have a length more than 0 hence are not blank, you will need to adjust cell references accordingly as I tested on a small sample of fake data.
Following this you can just loop:
For i = rows To 1 Step (-1)
If Cells(i,"G") = 0 Then r.rows(i).Delete 'My formula is in column "G"
Next
Or set up an auto-filter and delete entire rows of the visible cells:
Dim lrow As Integer
If Not WorksheetFunction.CountIf(Range("G:G"), "0") = 0 Then
Range("A1:G1").AutoFilter
Range("A1:G1").AutoFilter Field:=7, Criteria1:="0"
lrow = Cells(rows.Count, 7).End(xlUp).Row + 1
Range("G2:G" & lrow).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Range("A1:G1").AutoFilter
End If
The only problem with using a leading column to calculate for this is if you have a lot of data coming and going as you will need to replenish the formula, though you could use auto complete in the code i guess.

Removing a row in a table if it doesn't contain keyword

Right now I have a really long table in a Word doc which I populated from an Excel worksheet. It has 6 columns and I'm trying to code something in Word VBA that will go through all the rows in the table and delete the entire row if the cell in the first column DOES NOT start with an equal sign ("=").
For example, I'm only trying to keep the rows that has texts like,
"=1+S -03F7", "=1+M -06M1", etc. etc.
How would I code this? I can't give the code anything specific to look for since the parts after the equal sign will be different for every row.
So this wouldn't work, right?:
If Not ActiveDocument.Tables(83).Columns(1).Range.Text = "=" Then
EntireRow.Select
Selection.Delete
I guess I should reference to cells in column 1, not the column itself... Also, it doesn't work because it's only looking for things with just the equal sign... And I don't know how I can get it to select the row if it find the cell without the equal sign. I don't know how to match by case in the cell of the first column.
You can loop through the rows in the table using the Rows property. You can then find the first cell in that Row using the Cells property. You can then check just the first character of the Range:
Sub DeleteUnwantedRows()
Dim t As Table
Dim r As Row
Set t = ActiveDocument.Tables(1)
For Each r In t.Rows
If r.Cells(1).Range.Characters(1) <> "=" Then r.Delete
Next r
End Sub

Excel: Check if cell string value exists in column, and get all cell references to that string

I suspect this may be a job for VBA, which is beyond my abilities. But here's the scenario:
Column A in Sheet 1 (CAS1) contains x rows of text values
Column A in Sheet 2 (CAS2) contains x rows of text values
Part A - For each row value in CAS1, I need to know if the string is contained in any of the cells in CAS2. Not exact match, the string can be only part of the searched cells.
Part B - I need to know the cell value of each cell in CAS2 that contains the CAS1 value (if they do exist, they can be listed in the cells adjacent to the cell being searched in CAS1).
I've tried the following to attempt Part A, all to no avail:
vlookup(A1,sheet2!A:A,1,false)
NOT(ISNA(MATCH(A1,sheet2!A:A,0)))
ISNUMBER(MATCH(A1,sheet2!A:A,0))
COUNTIF(sheet2!A:A,A1)>0
IF(ISERROR(MATCH(A1,sheet2!A:A, 0)), "No Match", "Match")
I know some of the cell values in CAS2 contain the cell values in CAS1, so I don't know why they return false or No Match. I suspect it may be down to the nature of the text content. So here's some sample data:
CAS1
LQ056
RV007H
RV008
RV009H
TSN304
TSN305
CAS2
RV009-satin-nickel-CO.jpg
STR314.jpg
STR315.jpg
HCY001.jpg
RV008-oval-rad-CO.jpg
HCY001-BRAC006.jpg
Any help would be appreciated.
This problem can be faced through VBA (at least, I imagine the VBA solution much more easily than the possible Excel one). You need a macro that, for each row in CAS1, search the content in each row of CAS2 and returns you the address.
For Each cell In Sheets("CAS1").Range("A1:A" & Sheets("CAS1").Range("A1").End(xlDown).Row) '<-- check each cell of the range A1:A? of sheet CAS1 (adapt "A" and "1" if they're different)
recFound = 0 '<-- count how many findings there are
For Each cell2 In Sheets("CAS2").Range("A1:A" & Sheets("CAS2").Range("A1").End(xlDown).Row) '<-- check in each cell of the range A1:A? of sheet CAS2 (adapt "A" and "1" if they're different)
If InStr(cell2.Value, cell.Value) <> 0 Then '<-- if the value in cell is contained in the value in cell2..
recFound = recFound + 1 '<-- account the new finding
cell.Offset(0, recFound) = Split(cell2.Address, "$")(1) & Split(cell2.Address, "$")(2) '<--write the address on the right of the currently searched cell
End If
Next cell2
Next cell
All the above should be enclosed in a macro, e.g. Sub makeMySearch(), that should be run to get the results. As commented in my code, I'm assuming that data are in A1:A? of both sheets; but they of course might be, for example, in B5:B? of the sheet 1 and in C7:C? of the sheet 2. You need clearly to adapt the code to your current data.
There's no need for VBA. Some simple array-formulas can do the job.
To see if the entry in CAS1 is present in CAS2:
=OR(ISNUMBER(SEARCH(A2,CAS2_)))
will return TRUE or FALSE. BUT this formula has to be entered by holding down CTRL-SHIFT while hitting ENTER If you do this correctly, Excel will place braces {...} around the formula that you can see in the formula bar.
The SEARCH function returns an array of results, which will be either the #VALUE! error, or a number.
In order to return the address, the following array-formula can be entered adjacent to a cell in CAS1:
=IFERROR(ADDRESS(LARGE(ISNUMBER(SEARCH($A2,CAS2_))*ROW(CAS2_),COLUMNS($A:A)),1),"")
Fill right for the maximum number of addresses possible, then select the group and fill down.
In this case, the array being returned is a string of either 0's, or 1 * the row number (i.e. the row number). I assumend the data in CAS2 was in column A, but you can change the column number if needed (or even compute it if necessary, by replacing the 1 in the ADDRESS function with COLUMN(CAS2_))
CAS1_ and CAS2_ are either named ranges, or absolute range references to the two text groups.

Getting a total copied set of rows in VBA and storing it in a variable

I have a fairly simple syntax question:
I'm trying to copy and paste n rows from one excel file to another. In addition, I'd like to store the total copied rows into a variable.
Can someone help me accomplish this?
For example:
1)
Activate CSV file
Apply Filter to Column B (Page Title) & uncheck "blanks" ("<>") filter**
Windows("Test_Origin.xlsm").Activate
ActiveSheet.Range("$A$1:$J$206").AutoFilter Field:=2, Criteria1:="<>"
2)
Copy Filtered Lines with data (Excluding Row 1)
Range("B2:F189").Select
Selection.Copy
copiedRowTotal = total *FILTERED* rows copied over from original sheet, then Test Number iterates that many times
copiedRowTotal = Selection.Rows.Count
MsgBox copiedRowTotal
Thanks
An indirect way to do this is
Range("B2:F189").Copy
Range("M2").PasteSpecial xlPasteValues
copiedRowTotal = Selection.Rows.Count
Selection.Clear
The code copies the range & does a paste special operation on a separate location.
By doing this, only filtered rows are copied to M2 & the area (where the filtered rows are pasted) is highlighted when PasteSpecial operation is done.
Doing a Selection.Rows.Count gives one, the number of filtered rows that were pasted.
After figuring out the number of filtered rows, the selection is cleared up.
I don't believe there is a way to get the visible cell count directly. I tried using the 'SpecialCells(xlSpecialCellsVisible)' function, but could not get the correct count with a filter applied. Here is a quick function I wrote that works with a filter applied.
Also be aware that sometimes a filter can mess with the selected range at times, so it's something to note.
Public Sub TestIt()
Dim visibleCount As Long
visibleCount = GetVisibleCount(Sheets(1).Range("A2:H3000"))
MsgBox visibleCount
End Sub
Public Function GetVisibleCount(rng As Range) As Long
Dim loopRow As Range
GetVisibleCount = 0
For Each loopRow In rng.Rows
If loopRow.Hidden = False Then
GetVisibleCount = GetVisibleCount + 1
End If
Next loopRow
End Function
copiedrowtotal = selection.rows.count ' its not selection.totalcells
I think this would do the trick
After seeing your update let me tell you probably these would work
dim i as long
i = Application.WorksheetFunction.Subtotal(2,worksheets("Sheet").Range("B2:F189"))
Now i has the number of filtered rows in it! If you have included header in your range then do -1 at the end else just leave it up
argument 2 in subtotal is => counting the rows and then sheet name
and then specify range to count filtered rows
instead I would select only one column if you applied filter for many columns!
Hope it helps dont forget to accept an answer ! :

Excel pulling data from certain cells

I have a file that I only want to extract cells B9, B19, B29, etc etc etc in a pattern throughout the entire file. I would preferably like it to be extracted to a different excel file or someway so that I can do stuff with only those cells in another excel worksheet.
Potentially, I may have several excel files that I may need to do this sort of thing so if there were a way where I had the same format throughout a lot of files that I could always extract cells B9, B19, B29 that would be great. any help appreciated
I looking for syntax if possible
EDIT
Was thinking if I could somehow make an excel IF statement saying if Row has a 9 in it and the row is B then print it somewhere but I want it printed in a column
EDIT 2
I just want column B not A like I mentioned before.
B9, B19,B29,B39 through the whole file
Just in case you want to do it with code:
Sub Test()
'Assumes Sheet1 has your values and Sheet2 will be the data extracted from every row ending in 9
Dim iCounter As Long
Dim newSheetRow As Long
Dim aValue As String
Dim bValue As String
newSheetRow = 1
'Start and nine and increment by 10 till you reach end of sheet
For iCounter = 9 To Sheet1.Rows.Count - 1 Step 10 'NOTE: You may not want to do it by RowCount, but just showing you could
aValue = Sheet1.Range("A" & iCounter)
bValue = Sheet1.Range("B" & iCounter)
Sheet2.Range("A" & newSheetRow).Value = "We were on row: " & iCounter
Sheet2.Range("B" & newSheetRow).Value = aValue
Sheet2.Range("C" & newSheetRow).Value = bValue
newSheetRow = newSheetRow + 1
Next iCounter
MsgBox "Done"
End Sub
You could use the INDIRECT function. It takes a cell reference as a text string and returns the value in that cell. So instead of using
=data!a9
to get the value in sheet "data" in cell a9, you use
=indirect("data!a9")
You can also use r1c1 notation, like this:
=indirect("data!r9c1",false)
From there you can use the ROW and COLUMN functions to go in steps of 10:
=INDIRECT("data!r"&-1+10*ROW()&"c"&COLUMN(),FALSE)
If you put this formula in A1 of your output sheet and then copy and paste it down and across, it will give you the values in data!A9, data!A19, data!A29,... in cells A1, A2, A3... Depending on how you want your output arranged, you might have to modify the cell reference string.
Depending on how often you want to do this depends on how you need to do it, if it's a one of them some simple excel commands might help.
e.g.
In Cell C1 put the following:
=MOD(ROW(),10)
then replicate this down to the bottom of your data. the command will return the numbers 1 through to 0. You can then filter the data on column C where value is 9 then select the visible rows and copy the data to a new sheet.
ROW() ' this returns the ROW number of cell the command is in.
MOD(number, divisor) ' this basically divides one number by the other and returns the remainder. so row 9 / 10 = 0 remainder of 9, row 19 / 10 = 1 remainder of 9.
Hope this helps.