merge Excel sheets as values - excel

I am using some code (found via: http://www.extendoffice.com/documents/excel/1184-excel-merge-multiple-worksheets-into-one.html) to merge 5 sheets, each with 1000 rows.
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
This seems to work perfectly, other than I need to have the sheets combined using a 'paste as values' methodology (as my individual sheets have many formulas, and I just want to combine them as text versions).
Can this code be easily changed to 'paste as values'?
Thanks.

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).Copy
Sheets(1).Range("A65536").End(xlUp)(2).PasteSpecial xlPasteValues
Next
End Sub
Does this work? If so, we can get working on removing .select to make this a little bit more "tight". I already did it on the .Copy line (can you see what I did?)
Edit: This almost gets there - I think you'll hit an issue on the pasting part, but I can fix that. Just tell me, in your original code, what is the CurrentRegion that you're selecting? What's trying to be copy/pasted?
Edit 2: Okay, I think I've got it finally. The issue is your using Sheets(1), Sheets(2). I don't know how your document is, but the following works with these assumptions: You have the "unchanging" sheet active (this is the sheet with your magical formulas). Just have this active and run the macro below.
Sub Combine()
Dim J As Integer, noRows As Integer
Dim ws1 As Worksheet, ws2 As Worksheet, magicWS As Worksheet
' Note, you need to have the worksheet where you do all of your formulas open and be the active sheet.
Set magicWS = ActiveSheet
Set ws1 = Sheets.Add(after:=magicWS)
ws1.Name = "Combined"
On Error Resume Next
'Now, I assume that your main (unchanging) worksheet is the FAR LEFT most
'Then, the second worksheet is the new "Combined". If you look along the bottom, every worksheet RIGHT of "Combined" will need
'to be added to this WS.
'First, let's get the headers from the third sheet:
ws1.Cells.Rows(1).Value = Sheets(3).Cells.Rows(1).Value
'Now, let's add the data to "Combined"!
For J = 3 To Sheets.Count
noRows = Sheets(J).Range("A1").CurrentRegion.Rows.Count
Sheets(J).Range("A1").CurrentRegion.Offset(1, 0).Resize(noRows - 1).Copy
ws1.Range("A65536").End(xlUp)(2).PasteSpecial xlPasteValues
Next J
Application.CutCopyMode = False
End Sub

Related

VBA macro making out of memory issue

I have "Out of memory" issue with my Excel and VBA when I try to run macro below
Sub CopyPaste() ' macro to copy dynamic range
Dim lRow As Long
Dim sht As Worksheet
Set sht = Sheets("SQL")
sht.Activate
lRow = sht.Cells(sht.Rows.Count, 2).End(xlUp).Row
sht.Range("A1:Q" & lRow).Copy
Workbooks.Add
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Columns("A:Q").EntireColumn.AutoFit
End Sub
My idea is to copy dynamic range from SQL tab in excel and paste to new workbook as values, columns to be autofit and all cells centered.
I have powerful machine at home, tried to reboot it and restart excel just in case.
Please, try the next adapted code. It does not activate, select anything. They are useless, only consuming Excel resources. Since you try copying only values, you also do not need using Clipboard:
Sub CopyPaste() ' macro to copy dynamic range
Dim lRow As Long, sht As Worksheet
Set sht = Sheets("SQL")
lRow = sht.cells(sht.rows.count, 2).End(xlUp).row 'last row on B:B column
Workbooks.Add
With sht.Range("A1:Q" & lRow)
ActiveSheet.Range("A1").Resize(.rows.count, .Columns.count).Value = .Value
End With
Columns("A:Q").EntireColumn.AutoFit
End Sub
If B:B is not the column you like to be the reference for the last used range cell, please change it using the necessary column number (instead of 2 in sht.cells(sht.rows.count, 2))
If you like using Clipboard, the next code will be suitable:
Sub CopyPaste() ' macro to copy dynamic range
Sheets("SQL").Copy 'it creates a new workbook with THAT single sheet
'in case of existing columns after Q:Q, use the next code to clear. If not, delete the next code lines:
Dim lastCol As Long
lastCol = ActiveSheet.cells(1, .ActiveSheet.Columns.count).End(xlToLeft).column
If lastCol > 17 Then
Range(cells(1, 18), cells(1, lastCol)).EntireColumn.Clear
End If
End Sub
If no any column after Q:Q, the code may have only a code line...

Copy and paste values only after filtering data in vba [duplicate]

I have two sheets. One has the complete data and the other is based on the filter applied on the first sheet.
Name of the data sheet : Data
Name of the filtered Sheet : Hoky
I am just taking a small portion of data for simplicity. MY objective is to copy the data from Data Sheet, based on the filter. I have a macro which somehow works but its hard-coded and is a recorded macro.
My problems are:
The number of rows is different everytime. (manual effort)
Columns are not in order.
Sub TESTTHIS()
'
' TESTTHIS Macro
'
'FILTER
Range("F2").Select
Selection.AutoFilter
ActiveSheet.Range("$B$2:$F$12").AutoFilter Field:=5, Criteria1:="hockey"
'Data Selection and Copy
Range("C3").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("Hockey").Select
Range("E3").Select
ActiveSheet.Paste
Sheets("Data").Select
Range("D3").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Hockey").Select
Range("D3").Select
ActiveSheet.Paste
Sheets("Data").Select
Range("E3").Select
Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
Selection.Copy
Sheets("Hockey").Select
Range("C3").Select
ActiveSheet.Paste
End Sub
Best way of doing it
Below code is to copy the visible data in DBExtract sheet, and paste it into duplicateRecords sheet, with only filtered values. Range selected by me is the maximum range that can be occupied by my data. You can change it as per your need.
Sub selectVisibleRange()
Dim DbExtract, DuplicateRecords As Worksheet
Set DbExtract = ThisWorkbook.Sheets("Export Worksheet")
Set DuplicateRecords = ThisWorkbook.Sheets("DuplicateRecords")
DbExtract.Range("A1:BF9999").SpecialCells(xlCellTypeVisible).Copy
DuplicateRecords.Cells(1, 1).PasteSpecial
End Sub
I suggest you do it a different way.
In the following code I set as a Range the column with the sports name F and loop through each cell of it, check if it is "hockey" and if yes I insert the values in the other sheet one by one, by using Offset.
I do not think it is very complicated and even if you are just learning VBA, you should probably be able to understand every step. Please let me know if you need some clarification
Sub TestThat()
'Declare the variables
Dim DataSh As Worksheet
Dim HokySh As Worksheet
Dim SportsRange As Range
Dim rCell As Range
Dim i As Long
'Set the variables
Set DataSh = ThisWorkbook.Sheets("Data")
Set HokySh = ThisWorkbook.Sheets("Hoky")
Set SportsRange = DataSh.Range(DataSh.Cells(3, 6), DataSh.Cells(Rows.Count, 6).End(xlUp))
'I went from the cell row3/column6 (or F3) and go down until the last non empty cell
i = 2
For Each rCell In SportsRange 'loop through each cell in the range
If rCell = "hockey" Then 'check if the cell is equal to "hockey"
i = i + 1 'Row number (+1 everytime I found another "hockey")
HokySh.Cells(i, 2) = i - 2 'S No.
HokySh.Cells(i, 3) = rCell.Offset(0, -1) 'School
HokySh.Cells(i, 4) = rCell.Offset(0, -2) 'Background
HokySh.Cells(i, 5) = rCell.Offset(0, -3) 'Age
End If
Next rCell
End Sub
When i need to copy data from filtered table i use range.SpecialCells(xlCellTypeVisible).copy. Where the range is range of all data (without a filter).
Example:
Sub copy()
'source worksheet
dim ws as Worksheet
set ws = Application.Worksheets("Data")' set you source worksheet here
dim data_end_row_number as Integer
data_end_row_number = ws.Range("B3").End(XlDown).Row.Number
'enable filter
ws.Range("B2:F2").AutoFilter Field:=2, Criteria1:="hockey", VisibleDropDown:=True
ws.Range("B3:F" & data_end_row_number).SpecialCells(xlCellTypeVisible).Copy
Application.Worksheets("Hoky").Range("B3").Paste
'You have to add headers to Hoky worksheet
end sub
it needs to be .Row.count not Row.Number?
That's what I used and it works fine
Sub TransfersToCleared()
Dim ws As Worksheet
Dim LastRow As Long
Set ws = Application.Worksheets("Export (2)") 'Data Source
LastRow = Range("A" & Rows.Count).End(xlUp).Row
ws.Range("A2:AB" & LastRow).SpecialCells(xlCellTypeVisible).Copy

Auto-sort after summarizing into a Mastersheet

For my occupation, I am currently making an Excel list which summarizes 6 lists into one master list, removes the header (A1:J7) and then sorts them by a criteria. In this case it would be the J(priority) and A(secondary) columns.
I have gotten it to the point where it merges the lists I need into one masterlist, yet it still leaves a bit of a space at the top (Header not being removed) and splits the lists themselves by headers.
The basis for my VBA would be --
Sub Combine()
Dim J As Integer
On Error Resume Next
Sheets(1).Select
Worksheets.Add
Sheets(1).Name = "Combined"
Sheets(2).Activate
Range("A8").EntireRow.Select
Selection.Copy Destination:=Sheets(1).Range("A8")
For J = 2 To Sheets.Count
Sheets(J).Activate
Range("A8").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
Now the difficulty I'm personally having, is how would I go about adding the function to remove the header, and then sort itself after the criteria which was named above.
I've looked online and scoured through Google, but I cannot find any help that not only answers but also explains the issue I'm having so that I know 'why' something has to be done in a specified order.
If I follow what you're trying to do correctly:
Sub Combine()
Dim J As Integer
dim targetcell as range
Worksheets.Add before:=sheets(1)
Sheets(1).Name = "Combined"
set targetcell = sheets(1).range("a8") 'I think this is where you want to start
with Sheets(2)
.Range("A8").EntireRow.Copy Destination:=targetcell
set targetcell = targetcell.offset(1,0) 'down one row
end with
For J = 2 To Sheets.Count
With Sheets(J).Range("A8").CurrentRegion
' Sheets(J).Range("A9:A" & .rows.count -8).copy Destination:= targetcell
'this should be:
Sheets(J).Range("A9:A" & .rows.count -8).entirerow.copy Destination:= targetcell
'set targetcell = targetcell.offset(1,0)
'should be replaced with
Set targetcell = Sheets("combined").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
end with
Next J
targetcell.currentregion.sort key1:=targetcell 'assume sort on column A
End Sub

Copy/Paste Loop through worksheets to consolidate

I have a workbook which has approximately 300 worksheets. I'm trying to loop through each sheet, copy a specific range, and paste it on summary sheet. I need each successive paste to be put one row below the last used row. I'm newer to loops, but I think the amount of information being copied is excessive(causing an error), and I have come to understand that the .value method is much less memory intensive.
How do I incorporate the .value method to accomplish this? Here is the code I tried to write (again, I'm new to coding,sorry).
Sub Consolidation()
Dim ws As Worksheet
Sheets("Summary").Select
For Each ws InThisWorkbook.Sheets
ActiveSheet.Range("A" & Rows.Count).End(xLUp).Offset(1).Value ="ws.Range("BB1").End(xLToRight).End(xLDown).Select"
Next ws
End Sub
Alternatively, is there a better way to do this? Meaning, is the .value method the way to tackle this issue?
This question is similar than:
Simple Copy/Paste Loop not working on each worksheet
This is the way you can use the .Value
Sub WsLoop()
Dim ws As Worksheet
Dim Summary As Worksheet
Set Summary = ThisWorkbook.Sheets("Summary")
For Each ws In ThisWorkbook.Sheets
If Not ws.Name = "Summary" Then 'This will skip Summary.
Summary.Range("A1").Value = ws.Range("A1").Value
End If
Next ws
End Sub
Sub loop_through_all_worksheets_cpyPst()
Dim ws As Worksheet
Dim starting_ws As Worksheet
Set starting_ws = Sheets("startAtSheet")
'remember which worksheet is active in the beginning
For Each ws In ThisWorkbook.Worksheets
ws.Activate
If Not ws.Name = "SheettoPasteTo_skipCopy" Then 'This will skip Summary.
Range("A2:I2").Select
'my section range had only columns till i - edit the to last column
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("SheettoPasteTo_skipcopy").Select
'edit this sheet name to copy to
Range("A1").Select
Selection.End(xlDown).Select
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveSheet.Paste
ActiveCell.Offset(1, 0).Range("A1").Select
Selection.End(xlDown).Select
End If
ws.Cells(1, 1) = 1 'this sets cell A1 of each sheet to "1"
Next
starting_ws.Activate
'activate the worksheet that was originally active
End Sub

run macro on AutoFilter and show data in new sheet

Actually what i want to do , i have following data With Auto Filtering ,
-> I want to create new sheet for each unique Name selected from filtering .i.e. if John and Alex are selected then 2 new sheets should be created one for John and second for Alex , and each of them show own data (Name + No + R). When Next time if master sheet get updated then news data should be appended when i run macro. i'm using following code but its not working 100%.
Sub mycar()
x = 2
Do While Cells(x, 1) <> ""
If Cells(x, 1) = "John" Then
Worksheets("Sheet1").Rows(x).Copy
Worksheets("Sheet2").Activate
eRow = Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Paste Destination:=Worksheets("Sheet2").Rows(eRow)
End If
Worksheets("Sheet1").Activate
x = x + 1
Loop
End Sub
-> Here it copy only single data Written in the quotes.
-> Second time if i run this code , it is appending same data again with new data.
Help me to avoid this mistakes.
Thank you.
As discussed there is other possibility to set filter parameters in Array in procedure. The code would look like this one:
Sub Solution()
Dim shData As Worksheet
Set shData = Sheets("Arkusz1") 'or other reference to data sheet
Dim shNew As Worksheet
shData.Activate
'get unique values based on Excel features
Range("a1").AutoFilter
Dim myArr As Variant
myArr = Array("John", "max")
Range("a1").AutoFilter
Dim i As Long
For i = 0 To UBound(myArr)
shData.Range("$A$1").AutoFilter Field:=1, Criteria1:=myArr(i), _
Operator:=xlAnd
On Error Resume Next
Sheets(myArr(i)).Range("A1").CurrentRegion.ClearContents
If Err.Number = 0 Then
Range("A1").CurrentRegion.Copy Sheets(myArr(i)).Range("A1")
Else
Set shNew = Sheets.Add(After:=Sheets(Sheets.Count))
shData.Range("A1").CurrentRegion.Copy shNew.Range("A1")
shNew.Name = myArr(i)
Err.Clear
End If
Next i
'removing filter in master sheet
shData.Range("a1").AutoFilter
End Sub
Substitute Worksheets("Sheet1").Rows(x).Copy by Worksheets("Sheet1").Rows(x).EntireRow.Copy
And clear the destination worksheet before adding information.
I do quite similar exercise quite often. Therefore I provide full possible solution with some comments inside the code. It works for all unique values in column A and creates (if not exists) sheet with appropriate name equals to filter parameters.
Sub Solution()
Dim shData As Worksheet
Set shData = Sheets("Arkusz1") 'or other reference to data sheet
Dim shNew As Worksheet
'get unique values based on Excel features
'i guess some will not like it but I do :)
Range("a1").AutoFilter
Range("A1").CurrentRegion.Columns(1).Copy Range("ww1")
Range("ww1").CurrentRegion.RemoveDuplicates Columns:=1, Header:=xlYes
'be sure that range where you copy (like ww1) is empty range around
Dim myArr As Variant
myArr = Range(Range("ww2"), Range("ww2").End(xlDown))
Range("ww1").CurrentRegion.ClearContents 'some cleaning
Range("a1").AutoFilter '
Dim i As Long
For i = 1 To UBound(myArr, 1)
ActiveSheet.Range("$A$1").AutoFilter Field:=1, Criteria1:=myArr(i, 1), _
Operator:=xlAnd
On Error Resume Next
'this is for two reason- to check if appropriate sheet exists, if so to clean top area
'if you need to append you would comment this line
Sheets(myArr(i, 1)).Range("A1").CurrentRegion.ClearContents
If Err.Number = 0 Then
'if you need to append only you would need to set range-to-copy a bit different
Range("A1").CurrentRegion.Copy Sheets(myArr(i, 1)).Range("A1")
Else
Set shNew = Sheets.Add(After:=Sheets(Sheets.Count))
shData.Range("A1").CurrentRegion.Copy shNew.Range("A1")
shNew.Name = myArr(i, 1)
Err.Clear
End If
Next i
End Sub
This could not fully meet your requirements but could be a complete solution to improve accordingly.
Heading ##Below code is as per your requirement. Modify it based upon your requirement.
Private Sub Worksheet_Calculate()
Dim x As Integer
Dim rnge As Integer
x = Range(Selection, Selection.End(xlDown)).Count
rnge = ActiveSheet.UsedRange.SpecialCells(xlCellTypeVisible).Rows.Count
If Range("E1").Value > rnge Then
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets(2).Select
ActiveSheet.Paste
End If
End Sub

Resources