Filter and copy certain rows from multiple excel sheets to another - vba

I am using a workbook that has various sheets. I want to copy all the rows from the last 5 sheets that have the value "Pending" in their column "J". I want to create a new tab named "Pending week" and paste all these rows there. Any help would be really appreciated.
Thanks

You can create this yourself very easily if you just break it down:
Add a new Sheet
Name the sheet to Pending Week
Find the five latest sheets.
Create some kind of loop that copy paste row if cells in column J contains the value "Pending"
You have not provided any code, so I'll give you a base to work from:
You add a new sheet & name it using:
Worksheets.Add
ActiveSheet.Name = "Pending week"
Find the five latest sheets
To my knowledge, you can't find the latest sheets. Sheets doesn't contain the date and time of when they were created. But if we ignore that and expect the five latest sheets to be placed in the workbook to the far most right (Default position for newly created sheets). Then you need to figure out how many sheets you have and count backwards.
You can use: Worksheets.Count to count all the sheets. Use this number and count it backwards. My first thought would be to use a For Loop
Dim X As Integer
For X = (Worksheets.Count - 4) To Worksheets.Count
Next
X would be the identifier to find our latest sheets. So you should incorporate that into our loop below. You want to place the loop within this For Block.
Loop
There are many ways to find a value in a sheet, but you need to figure out what the last row of your sheets are. Without it we don't know when the code should stop.
You can use a Do Until Loop if there is a value in all J cells. Then you can simply insert the entire row into Pending week
It would look something like:
Dim XLrow As Integer
XLrow = 1
Do Until Worksheets(1).Cells(XLrow, "J") = ""
If Worksheets(1).Cells(XLrow, "J") = "Pending" Then
Worksheets(1).Range(XLrow & ":" & XLrow) = Worksheets("Pending week").Cells(XLrow, "J").Value
End If
XLrow = XLrow + 1
Loop
You will need to change the Range to the length of the range you want to copy. Note: the value Pending is case sensitive, so keep that in mind.
Alright, this is what you need to create your code. Of course you need to change values to fit your own workbook, but this is the base.

Related

Copying one sheet to another workbook based on one criteria

I have 2 different workbooks, main and copy.
Row 1 is meant for header/labeling the information it will be providing for both workbooks.
The "main" workbook will be using columns A to N. The copy will be using columns A to M.
The criteria to determine whether the code will be copying is the workbook, "main", column M.
If the cell contains "X" - it will copy column A to L, and N, to the workbook "copy". After which, it will go on to the next row to determine the same thing.
If the cell is empty, it will proceed down to the next row to determine the same thing as well.
The code has to be dynamic as new information will be added every 3 months, such as new rows added or the criteria changing from "X" to empty, or empty to "X".
I am a beginner in VBA excel, and have been trying out multiple codes but it doesn't seems to work. Would greatly appreciate it if someone could help me out with this.
Showing your code so far will help us a lot.
Maybe this helps a little:
Dim wks As Worksheet
Dim wks_copy As Worksheet
Set wks = Worksheets("main")
Set wks_copy = Worksheets("copy")
j = 2
For i = 2 To wks.UsedRange.Rows.Count
If wks.Cells(i, 13).Value = "x" Then
wks.Range(Cells(i, 1), Cells(i, 14)).Copy Destination:=wks_copy.Cells(j, 1)
j = j + 1
End If
Next i
This will copy the entire row. If you don't want to copy column M, I suggest clearing or hiding the column after copying.
If the macro runs again after 3 months, it will overwrite the existing data on Worksheet copy. But you should delete the worksheet's values before that, for example by using
Worksheets("copy").UsedRange.Offset(1, 0).ClearContents
or manually clearing the range.

VBA - Updating Master file from new file

I have a Master file which monitors shipment progress for my company. I update this on a weekly basis with progress on existing shipments (shipments which are already in the master file) and input new shipments. These updates come in the form of a update sheet which is in the same format as the master file. I have automated the input of new shipments, but I am stuck on how I could update the existing shipments progress.
Currently I perform a vlookup manually based off a shipment reference number. This is a pain because there are multiple shipment progress columns and I have to trawl through each new input to remove the vlookup formula.
FOR EXAMPlE: shipment reference is in column "C", shipment pickup is in column "AG", shipment dispatched is in column "AH" and shipment arrived is in column "AI".. and so on. In the master sheet I might have the reference number and pickup date. The update sheet might have the dispatch date for this shipment. I would want to take the dispatch date and copy it into the master file for this shipment.
I essentially want to search for blanks in each column of the master file and copy this data from the update file based on the shipment reference. I cannot copy and past over the master file data because I have added a lot of data manually the previous week which the updated file may not have or agree with.
Thank you for your help
Please see my attempted code:
Sub Eupdatedates()
Dim lr As Long, rw As Long, extRNG As Range
Set wb = Workbooks("masterfile.xlsm")
Set ws = wb.Sheets("RawDATA")
lastRow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row
Set extRNG = Workbooks("updatefile.csv").Worksheets("report").Range("C:AL")
For i = 33 To 38 ' columns which contain dates that need updating
ws.Range("$A$2:$CV$" & lastRow).AutoFilter field:=i, Criteria1:="=" 'filter out cells containing data
lastRow = ws.Range("B" & ws.Rows.Count).End(xlUp).Row ' find last row after filtering
firstRow = Range("Cells(2,i): Column(i)" & Rows.Count).Cells.SpecialCells(xlCellTypeBlanks).Row ' indentify first row after filtering
For rw = firstRow To lastRow ' loop through each each empty row cell and perform a vlookup to the update file
Cells(rw, i) = Application.VLookup(Cells(rw, i), extRNG, i - 2, False)
Next rw
Next i
End Sub
I am getting the error with "Range("Cells(2,i): Column(i)" I think I have looked online and cannot seem to find a way to define the range within a for loop. I am new to VBA so a lot of ground to make up. Any thoughts would be greatly appreciated!!
This is a job for VBA. I have done something similar in the past and used VBA to complete the task but it's not something I could code without having the workbooks in front of me. As a pointer I usually start with a big sheet of blank paper and write out the process in logical steps before beginning to code, e.g.
How many rows are there? (I want to know when to stop)
Where is the update sheet and what is it called?
start with first row (row number = 1)
What is the shipment reference (ship ref)?
select cell (row number, column of interest number)
is it blank? YES - find corresponding value in update sheet based on ship ref and update, NO - move to next column of interest
No more columns of interest for this row? - move to next row (row number +1)
etc.

Excel VBA - Extract Multiple Values from a Single Cell and Associate Values in Source Cell's Row

To preface this, I have very little experience in Excel VBA, but have used some VBA in Access.
I have a file which may contain multiple values in a single cell that need to be extracted out onto individual rows, and then have the data in multiple columns from the source row re-associated with the extracted values.
The multiple values in the single cell that need to be extracted are always in a uniform format. The cell may contain any number of sets of (), but the value I need to extract is always between the 2nd : and the closing ). This is the 'Identifier'.
For example:
(00050008009:STC:363711188)(00040022506:NYC:652263975)
Would need to extract these values onto individual rows:
363711188
652263975
All remaining values from the Source Row the value was extracted from then need to be re-associated with the value.
For example, my file may look like this:
Original File Format
I then need the file to appear as follows, on a new tab:
New File Format
I believe that a module making use of a loop, or multiple loops, is likely what is needed, but I have no idea of how to go about doing this in Excel. I'm open to all solutions. Any help is greatly appreciated! Thank you!
Without writing it for you, here are some pointers to get you started.
You'll need to loop through each cell in the column that contains the information you're looking for. For this, look into Worksheet.Range.
As you go through each cell, you'll need to examine the data that is actually entered into that cell. Using the Worksheet.Range.Value you can extract the contents of the cell.
Use excels string functions to parse the cell value into the values your looking for. Ex: InStr, InStrRev, etc... See this link for your options and usage for each function.
Finally you'll need to insert a row for each value that you find. Lookup Worksheet.Rows.Insert.
This should be the basic framework for what you need to do.
you may want to start with this code:
Option Explicit
Sub main()
Dim myArr As Variant
Dim cell As Range
Dim iRow As Long, nArr As Long
With Worksheets("batches").Range("A1").CurrentRegion '<--| change "batches" with your actual sheet name
For iRow = .Rows.Count To 2 Step -1 '<--|loop through data rows backwards, not to process rows multiple times
Set cell = .Cells(iRow, 3) '<--| 3rd column of current row is being processed
cell = Mid(cell, 2, Len(cell) - 2) '<--|get the cell value between first and last bracket
myArr = Split(cell, ")(") '<--|parse the resulting string with ")(" as delimiter and obtain and array
nArr = UBound(myArr) '<--| calculate the array size
If nArr > 0 Then '<--| if more than one element in array...
With .Rows(iRow) '<--|... then refer to entire current row
.Offset(1).Resize(nArr).Insert '<--| ...insert n-1 rows...
.Resize(nArr + 1).Value = .Value '<--|...duplicate current row into newly inserted ones
End With
cell.Resize(nArr + 1).Value = Application.Transpose(myArr) '<--|fill 3rd column of current and newly inserted rows with array elements
End If
Next iRow
For iRow = 2 To .Rows.Count '<--|loop through data rows
With .Cells(iRow, 3) '<--| 3rd column of current is being processed
.Value = Right(.Value, Len(.Value) - InStrRev(.Value, ":")) '<--| "finish" it
End With
Next iRow
End With
End Sub
As per your example, it assumes that your data start from cell "A1" and there's no blank row or column between it and the bottom-right cell of your data

How to select column and display its current format using VBA Macro?

Please find my requirement below for which I am unable to find any solution:
1. Iterate over workSheet from workbook
2. Find all the columns containing date values using current format/type of column (Here is a trick. Worksheet is not static, it can contain any number of columns containing date values. Columns containing date values may have any name. And such worksheets can be more than one in number)
3. Apply macro on date columns for date formatting (below macro) if "Flag" value is "y"
<code>
Sub FormatDate()
If wksSecDist.Range("Flag").value = "y" Then
LastRowColA = Range("X" & Rows.Count).End(xlUp).Row
' Here I am finding total number of rows in column X
wksSecDist.Range("X2", "X" & LastRowColA).NumberFormat = "dd/mmm/yyyy"
' Here applying specified date format to Range("X2", "X10") [if last row index for column X is 10]
End If
End Sub
</code>
I am just a beginner to VBA.
Thanks in advance.
I suspect you didn't find a solution on the internet because you looked simply for a solution and not the parts needed to build your own solution.
You mention you are a VBA beginner, please take the below answer to be of educational use and begin you in getting you where you need your tool to be. Note, if it doesn't answer your question because of information that was not included, it has still answered your question and the missing information should form part of a new question. That said, lets get this function up and running.
From what you have written I have interpreted the requirement to be: -
Look over all worksheets in a workbook ('worksheets can be more than one in number')
Check every column to see if it holds a date value
If it does, set the whole column to a specific format
What is needed to accomplish this is iteration(loops), one to loop through all worksheet, and another to loop through all columns: -
The is pseudo code of the target: -
.For each Worksheet in the Workbook
..For each Column in the Worksheet
...If the Column contains dates then format it as required
..Process next column
.Process next Worksheet
We achieve this using a variable to reference a Worksheet and using a loop (For Each) to change the reference. The same goes for the columns.
Public Sub Sample()
Dim WkSht As Excel.Worksheet
Dim LngCols As Long
Dim LngCol As Long
'This loop will process the code inside it against every worksheet in this Workbook
For Each WkSht In ThisWorkbook.Worksheets
'Go to the top right of the worksheet and then come in, this finds the last used column
LngCols = WkSht.Range(WkSht.Cells(1, WkSht.Columns.Count).Address).End(xlToLeft).Column
'This loop will process the code inside it against every column in the worksheet
For LngCol = 1 To LngCols
'If the first cell contains a date then we should format the column
If IsDate(WkSht.Cells(2, LngCol)) Then
'Set right to the bottom of the sheet
WkSht.Range(WkSht.Cells(2, LngCol), WkSht.Cells(WkSht.Rows.Count, LngCol)).NumberFormat = "dd/mmm/yyyy"
End If
Next
Next
End Sub
Hopefully that has all made sense, this does work on the premise that the header row is always row 1 and there are no gaps in the columns, but these are separate issues you can approach when you're ready to.

Manipulating Excel spreadsheet, removing rows based on values in a column and then removing more rows based on values in another column

I have a rather complicated problem.
I have a log file that when put into excel the column "I" contains event IDs, and the column J contains a custom key that keeps a particular even grouped.
All i want to do is remove any rows that do not contain the value of say 102 in the event id column.
And THEN i need to check the custom key (column J) and remove rows that are duplicates since any duplicates will falsely show other statistics i want.
I have gotten as far as being able to retrieve the values from the columns using com objects and .entirecolumn cell value etc, but I am completely stumped as to how i can piece together a solid way to remove rows. I could not figure out how to get the row for each value.
To give a bit more clarity this is my thought process on what i need to do:
If cell value in Column I does not = 102 Then delete the row that cell contains.
Repeat for all rows in spreadsheet.
And THEN-
Read every cell in column J and remove all rows containing duplicates based on the values in column J.
Save spreadsheet.
Can any kind persons help me?
Additional Info:
Column I holds a string that is an event id number e.g = 1029
Column J holds a string that is a mix of numbers and letters = 1ASER0X3NEX0S
Ellz, I do agree with Macro Man in that your tags are misleading and, more importantly, I did indeed need to know the details of Column J.
However, I got so sick of rude posts today and yours was polite and respectful so I've pasted some code below that will do the trick ... provided Column J can be a string (the details of which you haven't given us ... see what Macro Man's getting at?).
There are many ways to test for duplicates. One is to try and add a unique key to a collection and see if it throws an error. Many wouldn't like that philosophy but it seemed to be okay for you because it also gives you a collection of all the unique (ie remaining) keys in Column J.
Sub Delete102sAndDuplicates()
Dim ws As Worksheet
Dim uniques As Collection
Dim rng As Range
Dim rowPair As Range
Dim iCell As Range
Dim jCell As Range
Dim delRows As Range
Set ws = ThisWorkbook.Worksheets("Sheet1")
Set rng = Intersect(ws.UsedRange, ws.Range("I:J"))
Set uniques = New Collection
For Each rowPair In rng.Rows
Set iCell = rowPair.Cells(, 1)
Set jCell = rowPair.Cells(, 2)
On Error Resume Next
uniques.Add jCell.Value2, jCell.Text
If Err = 457 Or iCell.Value2 = 102 Then
On Error GoTo 0
If delRows Is Nothing Then
Set delRows = rowPair.EntireRow
Else
Set delRows = Union(delRows, rowPair.EntireRow)
End If
End If
Next
If Not delRows is Nothing then
MsgBox delRows.Address(False, False) & " deleted."
delRows.Delete
End If
End Sub
There are a number of ways in which this can be done, and which is best will depend on how frequently you perform this task and whether you want to have it fully automated. Since you've tagged your question with VBA I assume you'll be happy with a VBA-based answer:
Sub removeValues()
Range("I1").Select 'Start at the top of the I column
'We are going to go down the column until we hit an empty row
Do Until IsEmpty(ActiveCell.Value) = True
If ActiveCell.Value <> 102 Then
ActiveCell.EntireRow.Delete 'Then delete the row
Else
ActiveCell.Offset(1).Select 'Select the cell below
End If
Loop
'Now we have removed all non-102 values from the column, let`s remove the duplicates from the J column
Range("A:J").RemoveDuplicates Columns:=10, Header:=xlNo
End Sub
The key line there is Range("A:J").RemoveDuplicates. It will remove rows from the range you specify according to duplicates it finds in the column you specify. In that case, it will remove items from the A-J columns based on duplicates in column 10 (which is J). If your data extends beyond the J column, then you'll need to replace "A:J" with the appropriate range. Note that the Columns value is relative to the index of the first column, so while the J column is 10 when that range starts at A (1), it would be 2 for example if the range were only I:J. Does that make sense?
(Note: Using ActiveCell is not really best practice, but it's the method that most obviously translates to what you were trying to do and as it seems you're new to VBA I thought it would be the easiest to understand).