Add worksheet and combine data - vba

I have a workbook with 2991 worksheets. Each sheet containing information on trucks. Each worksheet is named city,state. For example Juneau, AK. Each worksheet is also formatted exactly the same.
I have code that copies the data from each workbook (excluding the headers) and places it in a "combined" worksheet.
I would like to expand the code so that when a worksheet gets copied the city and state are placed in new separate columns. For example for Jeneau, AK when the data gets copied next to each truck the city Juneau is placed in column F and the state "AK" is placed in column G.
I have the code listed below as well as example screenshots.
Sub Combine()
Dim J As Integer
On Error Resume Next
Sheets(1).Select
Worksheets.Add
Sheets(1).Name = "Combined"
Sheets(2).Activate
Range("A1").EntireRow.Select
Selection.Copy Destination:=Sheets(1).Range("A1")
For J = 2 To Sheets.Count
Sheets(J).Activate
Range("A1").Select
Selection.CurrentRegion.Select
Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Select
Selection.Copy Destination:=Sheets(1).Range("A65536").End(xlUp)(2)
Next
End Sub
Original Data
Combined Data

I think the following will do what you need:
Sub Combine()
Dim J As Integer
Dim ws1 As Worksheet
Dim wsCombined As Worksheet
Dim sheetName() As String
Dim pasteStartRow as Integer, pasteEndRow as Integer
On Error Resume Next
'Set ws1 to the first worksheet (I assume this has the header row in it)
Set ws1 = Sheets(1)
'Create wsCombined as the "Combined" worksheet
Set wsCombined = ThisWorkbook.Sheets.Add(ws1)
wsCombined.Name = "Combined"
'Copy the first row from ws1 to wsCombined
ws1.Rows(1).Copy Destination:=wsCombined.Range("A1")
'Loop through all sheets with data
For J = 2 To Sheets.Count
'Get the row on which we will start the paste
pasteStartRow = wsCombined.Range("A65536").End(xlUp).Row + 1
'Figure out the copy range
Sheets(J).Activate
Range("A1").Select
Selection.CurrentRegion.Select
'Copy/Paste
Selection.Offset(1, 0).Resize(Selection.Rows.Count - 1).Copy Destination:=wsCombined.Range("A" & pasteStartRow)
'Get the end row of the pasted data
pasteEndRow = wsCombined.Range("A65536").End(xlUp).Row
'Split the sheet name by comma and put it into an array
sheetName = Split(Sheets(J).Name, ",")
'write out the sheetname to the paste destination from above (using the start and end row that we grabbed)
'Added a trim() to the second item in the array (the state) in case the format of the name is <city>, <state>
wsCombined.Range("F" & pasteStartRow & ":" & "F" & pasteEndRow).Value = sheetName(0)
wsCombined.Range("G" & pasteStartRow & ":" & "G" & pasteEndRow).Value = Trim(sheetName(1))
Next
wsCombined.Activate
End Sub
I rewrote the bit before the for loop to remove all the selecting and activating and whatnot and also to get rid of the the ordinal sheet references and make everything more explicit. The rewrite also makes use of the Worksheets.Add() method to create the new worksheet.
The big change here is:
Grabbing the starting row of the paste destination into a variable
pasteStartRow so we can reuse it when we paste in the city and
state
Grabbing the ending row of the paste destination after we
paste into a variable pasteEndRow, again so we can reuse it with
City/State
Using an Array sheetName and Split() to grab the
comma delimited city, state value from the Sheets(J).name.
Writing the value of the city and state (sheetName(0) and
sheetName(1), respectively) into columns f and g on the
Combined worksheet.
I also added a wsCombined.activate at the end so that your combined worksheet is activate after everything is run.

Related

Edit cells in master workbook based on matched values from current workbook

The goal here is to compare values in column "A" between two workbooks (the current workbook is .xlsm, the target workbook is .xlsx). If any matches are found; the value in column "E" on the same row of matched value, is changed in the target workbook. It is mandatory to keep the workbooks separate in this case.
I decided to do this by selecting the first value in the current workbook (A2), applying it's value to a variable, then scanning column "A" in the target workbook to find a match (there should always be at least one match). Then changing the value of column "E" in the target workbook to "DSC" for those matched rows. Afterwards the selected cell in the current workbook is moved down one, and loops this process until a blank cell is reached.
Here is the code currently:
Sub DSC()
Dim RowCount As Long
secondWorkbook = "Master.xlsx"
currentWorkbook = ThisWorkbook.Name
Workbooks.Open ThisWorkbook.Path & "\" & secondWorkbook
' Define number of rows
RowCount = Workbooks("Master.xlsx").Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
' Select First Cell
Windows(currentWorkbook).Activate
Worksheets("Update Wipe").Activate
Range("A2").Select
Serial = ActiveCell.Value
Windows(secondWorkbook).Activate
Worksheets("Sheet1").Activate
' Run Function
For c = 2 To (RowCount - 1)
Windows(secondWorkbook).Activate
If Sheet1.Cells(c, 1).Value = Serial Then
Sheet1.Cells(c, 5) = "DSC"
Windows(currentWorkbook).Activate
Worksheets("Update Wipe").Activate
Selection.Offset(1, 0).Select
Serial = ActiveCell.Value
If Serial = "" Then Exit For
End If
Next c
End Sub
At the moment no errors are returned, however nothing is updating in the target workbook. It will open the target workbook on the computer. Bouncing the active workbook and worksheet back and forth to change the selected cell and update the variable may be the cause.
Here is a simplified working example.
You will want to change Range("A1:A20") to the range you want to compare.
You can also change Sheet("Sheet1") to the proper sheets.
AWorkbook is the .xlsm workbook.
MasterWorkbook is the .xlsx workbook.
As you can see, it's not necessary to use select.
You can loop through the cells using a For or For Each loop.
By nesting the for loops you can compare cells, though with larger datasets I would probably use Find and FindNext as opposed to looping through cells.
In this macro, I loop through each cell in our macro workbook, and compare it to each cell in the target workbook.
If the values match, I place DSC in the target workbook (column E)
Finally, close the workbook (SaveChanges:=True)
Sub DSC()
Dim AWorkbook, MasterWorkbook, c, d, ALastRow, MLastRow
Set AWorkbook = ThisWorkbook
Set MasterWorkbook = Workbooks.Open(ThisWorkbook.Path & "\" & "MasterWorkbook.xlsx", ReadOnly:=False)
ALastRow = AWorkbook.Sheets("Sheet1").Cells(Rows.CountLarge, "A").End(xlUp).Row
MLastRow = MasterWorkbook.Sheets("Sheet1").Cells(Rows.CountLarge, "A").End(xlUp).Row
For Each c In AWorkbook.Sheets("Sheet1").Range("A2:A" & ALastRow)
For Each d In MasterWorkbook.Sheets("Sheet1").Range("A2:A" & MLastRow)
If c.Value = d.Value Then MasterWorkbook.Sheets("Sheet1").Cells(d.Row, "E").Value = "DSC"
Next d
Next c
MasterWorkbook.Close (True)
End Sub
Load all of the values from Worksheets("Update Wipe")'s column A anto a dictionary. Open the Master workbook and Autofilter using the dictionary keys. Put "DSC" into all the visible cells in column E.
Option Explicit
Sub DSC()
Dim mWB As Workbook
Dim masterWorkbook As String, c As Long, rowCount As Long, serial As Variant
Dim k As Long, dict As Object
Set dict = CreateObject("Scripting.Dictionary")
dict.comparemode = vbTextCompare
With ThisWorkbook.Worksheets("Update Wipe")
For k = 2 To .Cells(.Rows.Count, "A").End(xlUp).Row
dict(.Cells(k, "A").Value2) = vbNullString
Next k
End With
masterWorkbook = "Master.xlsx"
Set mWB = Workbooks.Open(ThisWorkbook.Path & "\" & masterWorkbook)
With mWB.Worksheets("Sheet1")
If .AutoFilterMode Then .AutoFilterMode = False
With .Cells(1, "A").CurrentRegion
.AutoFilter field:=1, Criteria1:=dict.keys, Operator:=xlFilterValues
With .Resize(.Rows.Count - 1, 5).Offset(1, 0)
If CBool(Application.Subtotal(103, .Cells)) Then
.Columns("E").SpecialCells(xlCellTypeVisible) = "DSC"
End If
End With
End With
If .AutoFilterMode Then .AutoFilterMode = False
'optionally close the master workbook
'.Parent.Close savechanges:=True
End With
End Sub

Copy and Pasting Data based on Cell Input

I am attempting to copy and paste Rows from an original sheet (Ticket Sales) to a new Sheet (Rachel) based on the value in a specific Column for each Row (Column U). I want all the sales from Rachel to be copied over to another sheet, pretty much. No change in the formatting for the second sheet. This is what I have so far:
Sub CopyRachelDataPaste()
Dim i, LastRow
'Get Last Row
LasRow = Sheets("Ticket Sales").Range("A" & Rows.Count).End(xlUp).Row
'Clear Contents
Sheets("Rachel").Range("A2:AB3000").ClearContents
For i = 2 To LastRow
If Sheets("Ticket Sales").Cells(i, "U").Value = "Rachel" Then
Sheets("Ticket Sales").Cells(i, "U").EntireRow.Copy Destination:=Sheets("Rachel").Range("A" & Rows.Count).End(xlUp).Offset(1)
End If
Next i
End Sub
you must properly reference worksheet in all range definitions
like follows:
Option Explicit
Sub CopyRachelDataPaste()
Dim i As Long, lastRow As Long
Worksheets("Rachel").Range("A2:AB3000").ClearContents 'Clear Contents
With Worksheets("Ticket Sales") '<--| reference ticket worksheet
lastRow = .Range("A" & .Rows.Count).End(xlUp).Row '<--| get referenced worksheet column "A" last non empty row
For i = 2 To lastRow
If .Cells(i, "U").Value = "Rachel" Then .Cells(i, "U").EntireRow.Copy Destination:=Worksheets("Rachel").Range("A" & Worksheets("Rachel").Rows.Count).End(xlUp).Offset(1)
Next i
End With
End Sub

VBA - copy a dynamic range to a new workbook

I'm trying to figure out how to copy a dynamic range into a new workbook. The actual project is to generate monthly budget reports based on the user's choice of month. The overarching system tracks a number of budget lines, where each line has its own sheet, and each sheet holds 12 tables for the fiscal year for expenses to be input; it all feeds back into an annual budget sheet. Upon the user picking a month, a new workbook will be created, mirroring the number of sheets and filling each sheet with that month's table. Each table is a dynamic range.
What I've got below is a dry run to work out the mechanics, but the problem is that I cannot get the dynamic range to paste correctly:
Sub pasting()
On Error Resume Next
Dim x As Workbook
Dim y As Workbook
'set the budget tracking system as the active workbook
Set x = Workbooks("Save and copying proof of concept.xlsm")
'activate budget tracking system
x.Activate
Set y = Workbooks.Add
Dim z As Range
Dim w As Range
'test copying two cells in two sheets into new sheets in the new workbook
Set z = Workbooks("Save and copying proof of concept.xlsm").Sheets("Sheet1").Range("A1")
Set w = Workbooks("Save and copying proof of concept.xlsm").Sheets("Sheet2").Range("A1")
'call saveas option for monthly workbook
With y
Call save_workbook_newName
End With
'add 8 sheets to new workbook for 8 budget lines
Dim v As Worksheet
Dim i As Integer
For i = 1 To 7
Sheets.Add
Next i
'copy the specified range from the original sheet and into the newly created workbook.
z.Copy
y.Sheets("Sheet1").Range("A1").PasteSpecial Paste:=xlPasteValues
w.Copy
y.Sheets("Sheet2").Range("A1").PasteSpecial Paste:=xlPasteValues
'copy a dynamic range to a new workbook
x.Worksheets("Sheet3").Activate
Dim xRow As Long, xColumn As Long
'determine the row and column limits of the dynamic range
Range("A100").End(xlUp).Select
xRow = ActiveCell.Row
Range("D").End(xlToLeft).Activate
xColumn = ActiveCell.Column
'select the range specified by the dynamic boundaries
Range(Cells(1, 1), Cells(xRow, xColumn)).Select
Selection.Copy
'activate newly created workbook
y.Worksheets("Sheet3").Activate
'paste into the new workbook
Selection.PasteSpecial Paste:=xlPasteAll, operation:=xlNone, SkipBlanks:=False, _
Transpose:=False
End Sub
Sub save_workbook_newName()
Dim workbook_name As Variant
'display the SaveAs dialog box
'once a name is provided, the GetSaveAsFilename method gets the particular name and _
'assigns that name to the workbook_name variable
workbook_name = Application.GetSaveAsFilename
'if the user provides a filename, the true condition is executed, and if not (presses Cancel), the false condition is executed.
If workbook_name <> False Then
'the application.acriveworkbook property returns the workbooks to the current active window
'saves the file with the file name given by the user.
ActiveWorkbook.SaveAs Filename:=workbook_name & "xlsx"
Else
ActiveWorkbook.Close
End If
End Sub
This bit is the problematic code:
Range("A100").End(xlUp).Select
xRow = ActiveCell.Row
Range("D").End(xlToLeft).Activate
xColumn = ActiveCell.Column
'select the range specified by the dynamic boundaries
Range(Cells(1, 1), Cells(xRow, xColumn)).Select
It essentially only copies column A, even if it's told to activate column D and choose everything to the left of it (Columns A to C hold random numbers).
Using this method for selecting a dynamic range did not yield good results:
LR = Range("D1000").End(xlUp).Row
Set R1 = Range("D1:E" & LR)
Thanks, and I appreciate your help in this respect!
Another approach using .Resize. I think this method is a bit better than #Thomas Inzina because it goes along column and row headers (the .End methods) which are likely to not have empty cells. In Thomas'es example, if your data has empty cells in the last column, the code will copy incomplete table.
Sub copyTableIntoNewWorksheet()
' locate the dynamic range / table
Dim rngTable As Range
With ActiveSheet.[b2] ' top left cell of the dynamic range
Set rngTable = .Resize(Range(.Offset(0), .End(xlDown)).Rows.Count, _
Range(.Offset(0), .End(xlToRight)).Columns.Count)
End With
' create new worksheet
Dim wsNew As Worksheet
Set wsNew = Worksheets.Add
wsNew.Name = "New Sheet"
' copy table to new worksheet
rngTable.Copy wsNew.[a1] ' top left cell where to copy the table to
End Sub
The Range object can take two parameters Range([Cell1],[Cell2). Gereerally, you'll use the top left cell as first parameter and the bottom right cell as the second.
The first parameter of your code is Cells(1, 1) and the second is Cells(xRow, xColumn). The range will extend from Row 1 Column 1 to Row xRow, Column xColumn.
Range(Cells(1, 1), Cells(xRow, xColumn))
There is no need to select a range when copying and pasting. We can chain ranges methods together.
Here we set a range that starting in D100 extending to the leftmost column and then down to the last used cell in the list. We then copy it and paste it into y.Worksheets("Sheet3").Range("A1").
Foe example:
Dim rw As Long, Cell1 As Range, Cell2 As Range
Dim y As Workbook
Set x = Workbooks.Add
Set y = Workbooks("Book5.xlms")
rw = 100
Set Cell1 = Range("A" & rw)
Set Cell2 = Range("A" & rw).End(xlToRight).End(xlDown) 'This is the bottom left cell in the table
Set Target = Range(Cell1, Cell2)
Target.Copy x.Worksheets("Sheet1").Range("A1")
We can do all this on 1 line like this:
rw = 100
Range("D" & rw, Range("D" & rw).End(xlToRight).End(xlDown)).Copy y.Worksheets("Sheet3").Range("A1")

VBA - Copy data across worksheets

I'm looking to copy data across multiple worksheets. The names of the worksheets are in column L, I want to pick up the data from columns N:R, for that particular line, and then copy that into cells D17:D21 in the corresponding sheet.
Any assistance would be great.
Cheers
DRod
Sub Macro2()
Dim wb As Workbook
Dim ws As Worksheet
Dim wsGet As Worksheet
Dim LCell As Range
Dim sDataCol As String
Dim lHeaderRow As Long
sDataCol = "L" 'Change to be the column you want to match sheet names agains
lHeaderRow = 5 'Change to be what your actual header row is
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Sheet1") 'Change this to be your Summary sheet
'Check for values in sDataCol
With ws.Range(sDataCol & lHeaderRow + 1, ws.Cells(ws.Rows.Count, sDataCol).End(xlUp))
If .Row <= lHeaderRow Then Exit Sub 'No data
'Loop through sDataCol values
For Each LCell In .Cells
If LCell.Text <> "" Then
'Check if sheet named that value exists
If Evaluate("ISREF('" & LCell.Text & "'!A1)") Then
'Found a matching sheet, copy data from columns N:R to cells D17:D21 in the corresponding sheet
Set wsGet = wb.Sheets(LCell.Text)
wsGet.Range("N[ ]:R[ ]").Copy
LCell.Activate
Range("D17:D21").PasteSpecial Paste:=xlPasteValues, Transpose:=True
End If
End If
Next LCell
End With
End Sub
there are some mistakes
wsGet.Range("N[ ]:R[ ]") is not a valid syntax.
while wsGet.Range("N:R")is.
still, that way you get the entire columns, and not just the row you need of them.
you could use "Instersect()" method or the "Resize()" method on that range to get the range you need
with wsGet.Range("N[ ]:R[ ]").Copy you're using ".Copy" method on a "wsGet" sheet range.
use it on the same range (corrected as per the preceeding suggestion) of the "ws" sheet instead
with LCell.Activate, you're activating a "cell" instead of a "sheet".
you should use wb.Sheets(LCell.Text).Activate instead
but you don't need any sheet activation since you have already set "wsGet" as the "destination" sheet, so simply use ".PasteSpecial" method on it

Excel Copy whole row from a sheet to another sheet based on one column value

I need to copy an entire row from a sheet and paste in another sheet with same header consider a particular column value is equal to 89581.But my VBA throws 424 error.Please help.
Sub CopyData()
Dim c As Range
Dim Row As Long
Dim sheetUse As Worksheet
Dim sheetCopy As Worksheet
Set sheetUse = Sheets("Data1").Select
Set sheetCopy = Sheets("Data2").Select
Row = 3 'Assume same header in sheet2 as in sheet1
For Each c In sheetUse.Range("O3", Sheet1.Range("O65536").End(xlUp))
If c = 89581 Then
'copy this row to sheet2
Row = Row + 1
c.EntireRow.Copy sheetCopy.Cells(Row, 1)
End If
Next c
Application.CutCopyMode = False
End Sub
Here you go, build a reference to copy then copy and paste in one go.
Sub CopyToOtherSheet()
Dim sheetUse As Worksheet, sheetCopy As Worksheet, i As Long, CopyRange As String
Set sheetUse = Sheets("Data1")
Set sheetCopy = Sheets("Data2")
For i = 3 To sheetUse.Cells(Rows.Count, 15).End(xlUp).Row
If sheetUse.Cells(i, 15) = 89581 Then CopyRange = CopyRange & "," & i & ":" & i
Next i
sheetUse.Range(Right(CopyRange, Len(CopyRange) - 1)).Copy
sheetCopy.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteAll 'Change to values or formats or whatever you want
Application.CutCopyMode = False
End Sub
Assumed Data1 is the sheet with the data in and Data2 is the one to copy to.