VBA - Moving large number of records - some records missing - vba

I have a data set of around 1500 sales records. I have written a macro, which would create product category specific work books, which would have an individual work sheet for each product in the product category.
The macro is working as expected, but I have found out that it is consistently ignoring some products. I put debug statements to see if I am getting zero records when I filter based on the product code (since I use this selection to paste the records to a separate work sheet). The selection seems to be working fine, as I get the number of rows selected.
A pattern I saw was that the product codes which were having zero records were generally the first ones or the last ones to get processed before or after a file operation (either I open a category specific work book, or I am closing a work book). But even here, the table header was copied to the individual work sheet. Only the data rows were getting ignored.
Is there a chance where the macro is processing the records too fast, while there is some time lag in doing File I/O operations (which makes a few records to get ignored)?
I am attaching the code, which I have used for looping
'loop through each row and get the product id and the category (Ann & Bnn).
' Dim catWorkBook As Workbook
oProductCat = "0" 'the initial value set as 0, which would NEVER be a category
With wkScrap 'this is a rough sheet which has the product items and categories
For i = 2 To lProdRow
cProductCode = .Cells(i, 1).Value
cProductCat = .Cells(i, 2).Value
'FILE OPEN: will need to open a category specific .xls file
If (StrComp(cProductCat, oProductCat) <> 0) Then
'save the existing workbook
FileIO.CloseExcelFile oProductCat, catWorkBook
Set catWorkBook = Nothing 'clear all traces of the old worksheet
Set catWorkBook = CreateBlankWorkBook()
oProductCat = cProductCat
End If
'COPY DATA: Filtering on product code, and then moving it into a new
'worksheet
CopyCategoryToWorksheet cProductCode, catWorkBook
If i = lProdRow Then
'we are at the end of the loop. Proceed to close the current
'workbook
FileIO.CloseExcelFile oProductCat, catWorkBook
End If
Next
End With
Here is the function which does the actual copying
Private Sub CopyCategoryToWorksheet(prodCode As String, catWkBook As Workbook)
'check for a meaningful prod code
If (Trim(prodCode & vbNullString) = vbNullString) Then
Exit Sub
End If
Dim wkRData As Worksheet
Dim rRData As Range
Dim rDataMaxRows As Integer
Set wkRData = SalesReport.Sheet1
'We know that we have to create a work sheet for this product code.
'Let us do that first.
Dim prodCatSheet As Worksheet
catWkBook.Activate
Set prodCatSheet = catWkBook.Sheets.Add(After:=catWkBook.Sheets(catWkBook.Sheets.Count))
prodCatSheet.Name = prodCode
wkRData.Activate 'for this sub routine, all processing is happening on the raw data sheet
rDataMaxRows = Cells(rows.Count, 1).End(xlUp).Row
Set rRData = Range("A1:H" & rDataMaxRows)
rRData.AutoFilter 3, Criteria1:="=" & Trim(prodCode)
rRData.Select
Selection.SpecialCells(xlCellTypeVisible).Select
Selection.Copy
'activate the newly created sheet, and paste all the selected rows there
prodCatSheet.Activate
prodCatSheet.PasteSpecial
Set wkRData = Nothing 'just clear some memory
End Sub

Related

segregate the data based on their own value

I have data where list is dynamic. I would like to segregate the data base on their own value.I am unable to predict the exact value coming every time. Example : - This time I got company code as 1959809 and 1960574. I would like to filter data based on company code and would like to paste it in new workbook. This number will get change every time. Next time the company code may be 1960574 and 1963665.
I am thinking that we need to group the company code value so that we can have it in variable. However, I am unable to get the logic.
I am not getting any logic to do so. Hence, I don't have anything to show.
We should get two or more workbooks based on company code along with respective data.
Assuming your data has first column as 'Company Code' and starts from the first row of sheet, Following code will help you achieving your goal:
Sub ExportFilteredData()
Dim Codes As String, CodesArray, Code
Dim Wb As Workbook, CurSht As Worksheet
'Get the company codes from user as comma separated values
Codes = InputBox("Enter Company codes separated by comma")
CodesArray = Split(Codes, ",") 'Split company codes to array
'Save the data sheet reference and remove any applied filter
Set CurSht = ActiveSheet
CurSht.AutoFilterMode = False
'Filter data for each company code and save as new workbook
For Each Code In CodesArray
'Change the 'Field' value to the actual 'Company Code' column number
CurSht.Range("A1").AutoFilter Field:=1, Criteria1:=Trim(Code)
Set Wb = Workbooks.Add
CurSht.AutoFilter.Range.SpecialCells(xlCellTypeVisible).Copy Wb.Sheets(1).Range("A1")
'Change the path and filename as per your requirement
Wb.SaveAs ThisWorkbook.Path & "\" & Trim(Code) & ".xlsx"
Wb.Close False
CurSht.AutoFilterMode = False
Next
End Sub

VBA Macro Execution Order

I am running the following Macro on an excel workbook I have
Public Sub Iterate()
Dim i As Long
For i = 1 To 1
With Worksheets("Iterations")
Worksheets("Calculator").Range("AB6:AB16","AS8").Copy
.Cells(1, i).PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End With
Next
End Sub
What is plugged randomized in the AB column, is then invoking a calculation on all columns from "AG:AT"
now when I run the macro, random numbers are generated, and after they are generated --- I want the macro to copy the output from AB and AS to another sheet "Iterations" which it does.
Edit 2
The problem is that I need only "AB6:AB16" and "AS8" to be copied in the same instance, and not split it to two lines of code.
When I run the macro now, it copies all the columns to "AS8", instead of copying "AB6:AB16" and just the cell "AS8"
There are (at least) two ways to get around your issue:
Switch off automatic calculation while you are doing the two copies (the input data and the output data), so that the copying of the input data won't trigger a change to the input data which leads to a change to the output data prior to it being copied, or
Store both the input data and the output data in memory while the two copies are done.
As #2 is my preferred way to go, I will show you some code that does that:
Public Sub Iterate()
Dim i As Long
Dim inputValues As Variant
Dim outputValue As Variant
For i = 1 To 1000
With Worksheets("Iterations")
inputValues = Worksheets("Calculator").Range("AB6:AB16").Value
outputValue = Worksheets("Calculator").Range("AS8").Value
.Range(.Cells(1, i), .Cells(11, i)).Value = inputValues
.Cells(12, i).Value = outputValue
End With
Next
End Sub

VBA: Use one Excel Sheet to Insert to and/or Update another

Sheet 1 holds a full list of the current state of work orders
Sheet 2 holds recent changes to those work orders and any new work orders
Both sheets have the same format with data in columns A to L.
I need to use Sheet 2 to update the full list held in Sheet 1. Work orders have a unique identifier which is held in column A of each sheet.
In general terms:
Process each row of Sheet 2.
If a matching work order already exists in Sheet 1, update it.
If no matching work order exists in Sheet 1, add it as a new row in Sheet 1.
In column A is the work order number.
There may be better ways to do this, and as #Jeeped said, this has probably been asked before (though I couldn't find it). Hopefully the following is what you need. I've included lots of comments to help you understand the code and modify it should you need to.
Sub ProcessDelta()
'Define the worksheets
Dim shtDelta As Worksheet
Dim shtMaster As Worksheet
Set shtDelta = Worksheets("Sheet2")
Set shtMaster = Worksheets("Sheet1")
Dim intDeltaStartRow As Integer
'I assume there is a header row in the Delta sheet, if not, set this to 1
intDeltaStartRow = 2
Dim intMaxEverWorkOrders As Integer
'One of several ways to find the first blank row in the Master
'sheet is to start somewhere beyond the data and move up
'we use this later
intMaxEverWorkOrders = 1000000
Dim cellDeltaWorkOrder As Range
'Work order from Delta to be processed
Set cellDeltaWorkOrder = shtDelta.Cells(intDeltaStartRow, 1)
'For the destination to which we copy
Dim cellMasterWorkOrder As Range
Dim boolNewWorkOrder As Boolean
'Default to assume it's not a new workorder
boolNewWorkOrder = False
'We'll work from top to bottom in the Delta sheet. When the cell is blank we've finished
While cellDeltaWorkOrder.Value <> ""
'We're going to search for the "current" workorder from the Delta in the Master.
'If it's not there, we'll get an error. So we use "On Error" to handle it
On Error GoTo ErrorStep
'If there is no error, after the following line cellMasterWorkOrder will be the cell containing the matching workorder
Set cellMasterWorkOrder = shtMaster.Cells(WorksheetFunction.Match(cellDeltaWorkOrder.Value, shtMaster.Cells(1, 1).EntireColumn, 0), 1) '
'Reset error handling so any other errors are reported normally
On Error GoTo 0
'Check whether there was an error, if there was this was a new Workorder and needs to go at the end, so set the target cell accordingly
If boolNewWorkOrder = True Then
Set cellMasterWorkOrder = shtMaster.Cells(intMaxEverWorkOrders, 1).End(xlUp).Offset(1, 0)
boolNewWorkOrder = False 'reset this so we can check again for the next row to be processed
End If
'Output Row into Master
cellMasterWorkOrder.EntireRow.Value = cellDeltaWorkOrder.EntireRow.Value
'Move to next row in the Delta
Set cellDeltaWorkOrder = cellDeltaWorkOrder.Offset(1, 0)
Wend
'We don't want to run the error step at this point so ..
Exit Sub
ErrorStep:
'It wasn't found, which throws an error, and so it needs added as a new row.
boolNewWorkOrder = True
Resume Next
End Sub

Populate Serial Numbers on a different sheet

I have a macro to copy all the used rows in one Excel sheet (ExcelA) to another (ExcelB):
Sub CopyFromOneXL()
Dim myBook As Workbook, newBook As Workbook
Set myBook = ThisWorkbook
Set lRowMyBook = Range("A1").SpecialCells(xlCellTypeLastCell)
Set newBook = Workbooks.Open("C:\Users\user\Desktop\EXCEL\ExcelB.xlsx")
newBook.Activate
Set lRowNewBook = Sheets("Sheet1").Range("A1").SpecialCells(xlCellTypeLastCell)
lastRowNewBook = lRowNewBook.Row
lastRowMyBook = lRowMyBook.Row
lastRowNewBook = lastRowNewBook + 1
With newBook
myBook.Sheets("Sheet1").Rows("1:" & lastRowMyBook).Copy .Sheets("Sheet1").Rows(lastRowNewBook)
.Close savechanges:=True
End With
End Sub
ExcelB already uses ten rows (serial numbers from 1-10) and I'm using the above macro to add three more rows of data (which is in ExcelA). Is there any way to add serial numbers to ExcelB for the three newly added rows, starting from 11?
The number of rows in both sheets can vary but ultimately I want to add serial numbers to ExcelB starting from where it had left off.
OP wanted to index incremental entries where, conveniently, the index numbers matched the row numbers for entries copied with code from a different worksheet. Rather than add such an index with a loop in the code for copying the increments it was practical to add a formula (=ROW()) for it into the source sheet that would then copy across automatically with the existing code.
When I added the below code, it worked.
With newBook
myBook.Sheets("Sheet1").Rows("1:" & lastRowMyBook).Copy .Sheets("Sheet1").Rows(lastRowNewBook)
Set newLRowNewBook = Sheets("Sheet1").Range("A1").SpecialCells(xlCellTypeLastCell)
newLastRowNB = newLRowNewBook.Row
'MsgBox newLastRowNB
For i = lastRowNewBook To newLastRowNB
Cells(i, 1).Formula = "=Row()"
Next
.Close savechanges:=True
End With
Though the macro takes some time to run if there are 1000s of rows. Just wondering if there is any other way to achieve this without using For loop.
Thanks.

Macro to copy rows from multiple workbook to summary workbook with matching column value

I have different workbooks with different sheets with same Sheet name.(Book1,Book2,Book3,excel1,excel2,micorsoft etc) in a folder.
I would like to create way to have the entire row (when data is entered) transfered to a summary workbook with the matching value in a cell.please see the example table below.
If you notice the example below,I have a Book1 with worksheet1 (it also have different worksheets along with this one).
Now my requirement is to copy entire row with matching status column cell or cells (eg: NEW,research) into the workbook where macro is running,from all the workbooks in a folder.
I request if some one can help me with this macro that will be great.
Note:
Not always but Some times this data would change from time to time, so it would have to keep over-writing with the most up to date data. I would just like it all to consolidate onto 1 workbook so I can have the data from there.
Is this something that can be done easily? I've tried my luck at some macros but I can't seem to get it.
Book1
Worrksheet1
column A column B column C status comment column D
Update
New
Modified
New
New
Research
Research
I was lucky enough to get a code to copy from one sheet to other in a single book the code is below
Code:
Sub Foo()
Dim i As Long, iMatches As Long
Dim aTokens() As String: aTokens = Split("New,research", ",")
For Each cell In Sheets("Worrksheet1").Range("E:E")
If (Len(cell.Value) = 0) Then Exit For
For i = 0 To UBound(aTokens)
If InStr(1, cell.Value, aTokens(i), vbTextCompare) Then
iMatches = (iMatches + 1)
Sheets("Worrksheet1").Rows(cell.Row).Copy Sheets("final").Rows(iMatches)
End If
Next
Next
End Sub
Description:
This code will copy ALL rows content with the words matching NEW,research or any required in the column E : E from Worrksheet1 sheet to final sheet
Now change required in this is to copy from different workbooks in a folder(given path to directory) into single workbook in same or differ folder.
If i can have an option to email the copy like mentioned below link
will be great
Creating a Windows application which reads and writes excel spreadsheets + reads and writes emails
I'm not entirely sure I understand what you're after...But.
Open all the workbooks that you want copied.
Paste the following code into a standard module in one of the workbooks (it doesn't matter which one) Run it.
The code creates a new workbook and looks at every cell in row 1 of every workbook in every worksheet. (apart from the one that's just been created)
If it isn't blank it copies the entire column into the new workbook in the same worksheet number and in the same column position. Cheers.
Sub alltoone()
Application.ScreenUpdating = False
j = 0
ght = 0
Set nwrk = Workbooks.Add
For i = 1 To Workbooks.Count - 1
ght = Application.WorksheetFunction.Max(ght, Workbooks(i).Worksheets.Count)
Next i
If ght > nwrk.Worksheets.Count Then
Do
nwrk.Worksheets.Add
Loop Until ght = nwrk.Worksheets.Count
End If
For i = 1 To Workbooks.Count - 1
For k = 1 To Workbooks(i).Worksheets.Count
For t = 1 To 256
Set fez = Workbooks(i).Worksheets(k).Cells(1, t)
If Not fez.Value = Empty Then
fez.EntireColumn.Copy
nwrk.Worksheets(k).Columns(t).EntireColumn.PasteSpecial
End If
Next t
Next k
Next i
Set nwrk = Nothing
Set fez = Nothing
Application.ScreenUpdating = True
End Sub