Extract data from multiple worksheets to one sheet using vba - excel

I have a workbook contain about 50 worksheets (sheet 1, sheet 2, sheet 3,........, sheet 50).
I want to get the data in all of them into one sheet. I used following code for that.
Sub tgr()
Dim ws As Worksheet
Dim wsDest As Worksheet
Set wsDest = Sheets("Sheet1")
For Each ws In ActiveWorkbook.Sheets
If ws.Name <> wsDest.Name Then
'ws.Range("A2", ws.Range("A22:Y500").End(xlToRight).End(xlDown)).Copy
ws.Range("A12:Y60").Copy
wsDest.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
End If
'ActiveWorkbook.Save
Next ws
End Sub
But this code isn't working for all the sheets i have. it applies to random sheets.
What should i do to make it apply for all the sheets. (I have different rows in each sheet.)
And also above code runs for a long time.

The following code will consolidate data from all sheets in the workbook that is running the code.
Note that this is pasting just values (not formmating or formulas)
EDIT: Just for making this answer more clear. Using full qualifying of the target workbook and preventing to work with the active workbook, will guarantee that your looping through all the sheets. I address OPs request of looping through all sheets and not random ones. And also add a way to speed up the process.
Read the comments and adjust it to fit your needs:
Public Sub ConsolidateData()
' Declare and initialize the destination sheet
Dim destinationSheet As Worksheet
Set destinationSheet = ThisWorkbook.Worksheets("Sheet1")
' Loop through all worksheets in the workbook that is running the script
Dim sourceSheet As Worksheet
For Each sourceSheet In ThisWorkbook.Worksheets
If sourceSheet.Name <> destinationSheet.Name Then
' Set the source sheet's range
Dim sourceRange As Range
Set sourceRange = sourceSheet.UsedRange ' I'm using used range, but you could leave it as you had it in terms of a fixed range: sourceSheet.Range("A12:Y60").Copy
' Get first available cell in column A (from bottom to top)
Dim targetCell As Range
Set targetCell = destinationSheet.Range("A" & destinationSheet.Cells(destinationSheet.Rows.Count, "A").End(xlUp).Row).Offset(1, 0)
' Resize and assign values from source range (using value2 speeeds up things)
targetCell.Resize(sourceRange.Rows.Count, sourceRange.Columns.Count).Value2 = sourceRange.Value2
End If
Next sourceSheet
End Sub

Related

Excel macro FOR EACH loop to copy paste same range in different worksheets and paste to next column

I have several worksheets (Worksheet A, Worksheet B, Worksheet C) in a workbook. I want to copy the same range from each of these worksheets and paste them to another workbook's worksheet, each one going in the next column. I know how to write the code to copy, but the harder part is the pasting. This is what I'm thinking:
sub copypaste ()
dim wb as workbook 'this workbook
dim destination as workbook 'destination workbook
dim ws as worksheet
dim ws1 as worksheet '(in this workbook)
dim ws2 as worksheet '(in this workbook)
dim ws3 as worksheet '(in this workbook)
dim DestWorksheet as worksheet
For Each ws in wb.worksheets (referring to ws1, ws2, and ws3)
Range.("D1:D231").Copy
DestWorksheet.(I WANT TO PASTE DATA FROM WS1 in Column A in the destination worksheet, Ws2 in Column B, Ws3 in Column3) etc.
Try the following. This code uses indexes for both the worksheet and column at the same time, so at the nth sheet iteration values will also be pasted to the nth column.
Bear in mind that I have dropped .Copy. This function is not necessary if you are only copying values and for that use my code is faster. If you do need to copy more than merely values, replace the .Range(.Cells(1, i), .Cells(231, ... line to a copy paste line.
Sub copypasta()
Dim i As Integer
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
For i = 1 To wb.Sheets.Count
With Workbooks(DESTINATION).Sheets(DESTINATION)
.Range(.Cells(1, i), .Cells(231, i)).Value = wb.Sheets(i).Range("D1:D231").Value
End With
Next i
End Sub
Don't use copy and paste, that is inefficient
Just put the value of an range in another, in the location you want
DestWorksheet.Range("A1:A231").Value2 = Range("D1:D231").Value2
ws2.Range("B1:B231").Value2 = Range("D1:D231").Value2
ws3.Range("C1:C231").value2 = Range("D1:D231").Value2

How to copy values and formatting when copy entire sheet with VBA

I have the code below that works really well.
It copies the active worksheet and creates a new sheet with name based on a specific cell.
Can I modify this to not include formulas when copied? I only want Values and Formatting, so the new sheet is a static snapshot.
Sub Copyrenameworksheet()
Dim ws As Worksheet
Set wh = Worksheets(ActiveSheet.Name)
ActiveSheet.Copy After:=Worksheets(ActiveSheet.Name)
If wh.Range("C2").Value <> "" Then
ActiveSheet.Name = wh.Range("C2").Value
End If
wh.Activate
End Sub
How about the following as a general method to make a static copy of a worksheet:
Dim sht1 As Worksheet 'worksheet to copy from
Dim sht2 As Worksheet 'worksheet to paste to
Set sht1 = ThisWorkbook.Worksheets("Name of the Worksheet to copy from")
sht1.Cells.Copy 'Copy everything in the worksheet
Set sht2 = ThisWorkbook.Worksheets.Add 'create new blank worksheet
sht2.Cells.PasteSpecial xlPasteValues 'first paste values
sht2.Cells.PasteSpecial xlPasteFormats ' then paste formats
sht2.Name="Something" 'give a name to your new worksheet
Also please avoid using ActiveSheet and use explicit references to your worksheets instead.
I modified your code slightly to use variables for your original sheet and your copied sheet. I use .Value2 = .Value2 to remove formulas. Note that this will run into an error if you try to create multiple sheets using the same name in C2.
Sub Copyrenameworksheet()
Dim wsOrig As Worksheet, wsNew As Worksheet
Set wsOrig = Worksheets(ActiveSheet.Name)
wsOrig.Copy , wsOrig
Set wsNew = Worksheets(wsOrig.Index + 1)
If wsOrig.Range("C2").Value <> "" Then
wsNew.Name = wsOrig.Range("C2").Value
End If
wsNew.UsedRange.Value2 = wsNew.UsedRange.Value2
wsOrig.Activate
End Sub

Setting value using filtered data

I'm trying to open a sheet (Archive) from my inventory sheet, filter the data in the second sheet and then copy the filtered data to a sheet on the inventory. Everything is working except that the filtered data only copies the data from rows in the first contiguous range. My code is as follows
Dim LastRow As Long
Dim nOoFrOWS As Long
Dim oSht As Worksheet
Workbooks.Open ("C:\Inventory\Archive.xlsm") '<- at opening a workbook it becomes the active one
Set oSht = ActiveWorkbook.Worksheets("Archive") '<-- set the destination worksheet in the activeworkbook
With ActiveSheet
.ListObjects("Archive").Range.AutoFilter Field:=12, Criteria1:=mOrder
nOoFrOWS = .AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Cells.Count - 1 '# of rows in Inventory
End With
Unload Me
ThisWorkbook.Sheets("RAM").Range("A2:K" & nOoFrOWS).Value = oSht.Range("Archive[[QTY]:[RTK]]").SpecialCells(xlCellTypeVisible).Cells.Value
oSht.Parent.Close False
What am I doing wrong?
edit: I don't know if it is pertinent, but the range in the archive (from which I am copying) is not the entire table. I have more rows, but These are all I need for this application.
Also, is there a way to do this without the clipboard by using .value or am I stuck with using the copy paste method?
As your working with a table you can copy the visible cells in the databodyrange.
No need to activate or select anything - just work with the referenced files & sheets.
Sub Test()
Dim wrkBk As Workbook
Dim mOrder As Long
mOrder = 5
'You can reference the workbook without it being active.
Set wrkBk = Workbooks.Open("C:\Inventory\Archive.xlsm")
With wrkBk.Worksheets("Archive").ListObjects("Archive")
.Range.AutoFilter Field:=12, Criteria1:=mOrder
'Copy the DataBodyRange (Range would include the headers).
.DataBodyRange.Resize(, 11).SpecialCells(xlVisible).Copy Destination:=ThisWorkbook.Worksheets("RAM").Range("A2")
End With
End Sub

Copy all previously filtered data from all worksheets to another

I have a workbook with about 63 sheets. I'd like to take all filtered data (filtered by a macro) from all worksheets and paste them into a separate worksheet.
Worksheets DON'T have the same data range. They all would start on Column A Row 15 IF there is any data there at all. The filter macro filters for specific values in one of the columns hence the differentiation between rows in each sheet.
I need to copy all filtered data starting with a Range of A15 and the last row in the range would be AI. It's just a matter of how many rows if there are any rows to get the number for the AI in the range to copy over.
I got it to copy an entire sheet, not the filtered data, to another sheet but it only copied sheet 1.
Sub rangeToNew_Try2()
Dim newBook As Excel.Workbook
Dim rng As Excel.Range
Set newBook = Workbooks.Add
Set rng = ThisWorkbook.Worksheets("Sheet1").Cells.SpecialCells(xlCellTypeVisible)
rng.Copy newBook.Worksheets("Sheet1").Range("A1")
End Sub
You can use Worksheet.UsedRange to give you just the Range with data in, then you could apply your Range.SpecialsCells to give you just the filtered data.
To help debug your code, set a breakpoint and use the Immediate Window to see what the range is, i.e.:
?rng.Address
(The question mark prints out whatever follows.)
This function should do what you need:
Sub CopyFilteredDataToNewWorkbook()
Dim newBook As Excel.Workbook
Dim rng As Excel.Range
Dim sht As Excel.Worksheet
Dim rowoffsetcount As Long
Dim newsht As Excel.Worksheet
Set newBook = Workbooks.Add
' ThisWorkbook.Worksheets is the same as the Sheets or Worksheets object, but more explicit
For Each sht In ThisWorkbook.Worksheets
' Get the used rows and columns
Set rng = sht.UsedRange
' Offset the range so it starts at row 15
rowoffsetcount = 15 - rng.Row
Set rng = rng.Offset(rowoffsetcount)
' Check there will be something to copy
If (rng.Rows.Count - rowoffsetcount > 0) Then
' Reduce the number of rows in the range so it ends at the same row
Set rng = rng.Resize(rng.Rows.Count - rowoffsetcount)
' Check that there is a sheet we can copy it to
On Error Resume Next
Set newsht = Nothing
Set newsht = newBook.Worksheets(sht.Index)
On Error GoTo 0
' We have run out of sheets, add another at the end
If (newsht Is Nothing) Then
Set newsht = newBook.Sheets.Add(, newBook.Worksheets(newBook.Worksheets.Count))
End If
' Give it the same name
newsht.Name = sht.Name
' Get the range of visible (i.e. unfiltered) rows
' (can't do this before the range resize as that doesn't work on disjoint ranges)
Set rng = rng.SpecialCells(xlCellTypeVisible)
' Paste the visible data into the new sheet
rng.Copy newsht.Range("A1")
End If
Next
End Sub

Combine worksheets and add column in Excel

I have a worksheet that contains multiple tabs that identify different sources of data. I need to combine all the worksheets into one and add a column with the worksheet name as part of the new combined sheet.
I found the following code and if I cut/paste into my worksheet it works like a charm BUT I have several of these workbooks and I have to be able to recreate this process monthly.
My research indicates that I should create a com add in or recallable macro to do this but each time I have tried, the process fails. I would very much appreciate if somone could point me with the steps to do this in Excel (2013) and advise me if my code will work.
Thanks in advance.
Sub Combine()
Dim J As Integer, wsNew As Worksheet
Dim rngCopy As Range, rngPaste As Range
Dim Location As String
On Error Resume Next
Set wsNew = Sheets("Combined")
On Error GoTo 0
'if sheet does not already exist, create it
If wsNew Is Nothing Then
Set wsNew = Worksheets.Add(before:=Sheets(1)) ' add a sheet in first place
wsNew.Name = "Combined"
End If
'copy headings and paste to new sheet starting in B1
With Sheets(2)
Range(.Range("A1"), .Cells(1, Columns.Count).End(xlToLeft)).Copy wsNew.Range("B1")
End With
' work through sheets
For J = 2 To Sheets.Count ' from sheet 2 to last sheet
'save sheet name/location to string
Location = Sheets(J).Name
'set range to be copied
With Sheets(J).Range("A1").CurrentRegion
Set rngCopy = .Offset(1, 0).Resize(.Rows.Count - 1)
End With
'set range to paste to, beginning with column B
Set rngPaste = wsNew.Cells(Rows.Count, 2).End(xlUp).Offset(2, 0)
'copy range and paste to column *B* of combined sheet
rngCopy.Copy rngPaste
'enter the location name in column A for all copied entries
Range(rngPaste, rngPaste.End(xlDown)).Offset(0, -1) = Location
Next J
End Sub
You can add this code into your Personal Macro Workbook, and modify it so it acts on the ActiveWorkbook. That way, when you run it, it will operate on whichever workbook is selected in Excel.
Also worth qualifying all your sheet references with a workbook object reference. When you use (e.g.):
Sheets("Combined")
then by default it will refer to the ActiveWorkbook. Usually this is what you want (though it may not be), but working this way can cause problems if (for example) you open/activate a different workbook in your code, and that other workbook is now the target of your Sheets(....) reference. You resolve this by always being explicit about which workbook you're referring to: for example -
ThisworkBook.Sheets() 'the workbook containing the running code
ActiveWorkbook.Sheets() 'the selected workbook
Workbooks("test.xlsx").Sheets() 'named workbook
wb.Sheets() 'use a variable set to a workbook object
So, modifying your existing code:
Sub Combine()
Dim wb As Workbook
Dim J As Integer, wsNew As Worksheet
Dim rngCopy As Range, rngPaste As Range
Dim Location As String
Set wb = ActiveWorkbook
On Error Resume Next
Set wsNew = wb.Sheets("Combined")
On Error GoTo 0
'if sheet does not already exist, create it
If wsNew Is Nothing Then
Set wsNew = wb.Worksheets.Add(before:=wb.Sheets(1)) ' add a sheet in first place
wsNew.Name = "Combined"
End If
'copy headings and paste to new sheet starting in B1
With wb.Sheets(2)
.Range(.Range("A1"), .Cells(1, Columns.Count) _
.End(xlToLeft)).Copy wsNew.Range("B1")
End With
' work through sheets
For J = 2 To wb.Sheets.Count ' from sheet 2 to last sheet
'save sheet name/location to string
Location = wb.Sheets(J).Name
'set range to be copied
With wb.Sheets(J).Range("A1").CurrentRegion
Set rngCopy = .Offset(1, 0).Resize(.Rows.Count - 1)
End With
'set range to paste to, beginning with column B
Set rngPaste = wsNew.Cells(Rows.Count, 2).End(xlUp).Offset(2, 0)
'copy range and paste to column *B* of combined sheet
rngCopy.Copy rngPaste
'enter the location name in column A for all copied entries
wsNew.Range(rngPaste, rngPaste.End(xlDown)).Offset(0, -1) = Location
Next J
End Sub

Resources