Copy over data from one workbook to another - vba

I have an open workbook that has a bunch of macros in it, one of these macros is to copy data from this workbook and paste it into another workbook on a server. So far I can open the server workbook, and navigate to the right tab and cell but I cannot paste the data... My code is below:
Sub aggregate()
Dim m As String
Dim t As Integer
'opened workbook
Sheets("Month Count").Select
range("A2").Select
Do
m = ActiveCell.Value
t = ActiveCell.Offset(0, 1).Value
Set xl = CreateObject("Excel.Application")
Set xlwbook = xl.Workbooks.Open("\\LOCATIONOFOTHERWORKBOOKONSERVER")
xl.Visible = True
xlwbook.Worksheets("A").range("A2").Select
xlwbook.ActiveCell.Value = m **this is where my code breaks.**
xlwbook.ActiveCell.Offset(1, 0).Value = t
'HOW TO SAVE FILE AND CLOSE FILE?
Windows("GOBACKTOFIRSTWORKBOOK").Activate
ActiveCell.Offset(1, 0).Select
Loop Until ActiveCell.Value = "THE END"
End Sub

Something like below which will find a range from A2 to a cell contain "THE END" in column A of a sheet called "Month Count" in the ActiveWorbook, then open a second workbook ( I used C:\test\other.xlsm", goto sheet "A", and then put
A2 from the first book into A2 of the second book,
B2 from the first book into A3 in the second book,
A3 from the first book into A4 in the second book,
B3 from the first book into A5 in the second book etc
Note that in your code you are currently opening a new Excel instance, you should work on both workbooks in the same instance so that they can "talk"
Sub aggregate()
Dim Wb1 As Workbook
Dim Wb2 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim rng1 As Range
Dim rng2 As Range
Dim lngRow As Long
Dim lngCalc As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
lngCalc = .Calculation
End With
Set Wb1 = ActiveWorkbook
Set ws1 = Wb1.Sheets("Month Count")
Set rng1 = ws1.Columns("A").Find("THE END", , xlValues, xlWhole)
If rng1 Is Nothing Then
MsgBox "Did not find marker cell"
GoTo QuickExit
End If
Set rng1 = ws1.Range(ws1.[a2], ws1.Cells(rng1.Row, "A"))
Set Wb2 = Workbooks.Open("C:\test\other.xlsm")
Set ws2 = Wb2.Sheets("A")
For Each rng2 In rng1
ws2.[a2].Offset(lngRow, 0) = rng2
ws2.[a2].Offset(lngRow + 1, 0) = rng2.Offset(0, 1)
lngRow = lngRow + 2
Next
Wb2.Save
Wb2.Close
Wb1.Activate
QuickExit:
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = lngCalc
End With
End Sub

there is no point "activating" your workbooks.
you don't need to instantiate a second Excel if your macro is already running in Excel.
it would be much faster to do in one shot
I suspect your error comes from the fact xlwbook has not been activated when you use xlwbook.ActiveCell.
Below is my proposal for your copy/paste thing, the one by one way (or I should say 2 by 2).
Sub aggregate2()
Dim rngSource As Range
Dim rngDest As Range
Dim xlwbook As Workbook
Set rngSource = Sheets("Month Count").Range("A2:B2")
Set xlwbook = Workbooks.Open("\\LOCATIONOFOTHERWORKBOOKONSERVER")
Set rngDest = xlwbook.Range("A2:B2")
Do
rngDest.Value = rngSource.Value
Set rngSource = rngSource.Offset(1, 0)
Set rngDest = rngDest.Offset(1, 0)
Loop Until rngDest.Cells(1, 1) = "THE END"
xlwbook.close
End Sub

Related

Excel VBA - Copy mutiple column not in sequence order

I want to copy from one sheet into another. The macro should recognize the worksheet via name:
Dim Wb1 As Workbook, wb2 As Workbook, wB As Workbook
Dim rngToCopy As Range
Dim NewEnd As Long
Dim NewEnd2 As Long
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Sheets("CALC").Select
Worksheets("CALC").Range("B5:J25000").ClearContents
For Each wB In Application.Workbooks
If Left(wB.Name, 4) = "15B2" Then
Set Wb1 = wB
Exit For
End If
Next
If Not Wb1 Is Nothing Then
Set wb2 = ThisWorkbook
With Wb1.Sheets("Data")
Set rngToCopy = .Range("F7, H7, N7", .Cells(.rows.Count, "F").End(xlUp))
End With
wb2.Sheets("CALC").Range("B5:D5").Resize(rngToCopy.rows.Count).Value = rngToCopy.Value
End If
This line gives me an error:
Set rngToCopy = .Range("F7, H7, N7", .Cells(.Rows.Count, "F").End(xlUp))
How can I copy mutiple columns in this case?
You can use Union to merge multiple columns to 1 Range.
Dim LastRow As Long
LastRow = .Cells(.Rows.Count, "F").End(xlUp).Row ' get last row with data from column "F"
Set rngToCopy = Application.Union(.Range("F7:F" & LastRow), .Range("H7:H" & LastRow), .Range("N7:N" & LastRow))
rngToCopy.Copy
wb2.Sheets("CALC").Range("B5").PasteSpecial xlPasteValues

VBA: Copy cell from all worksheets and paste into column

New in VBA and learning on my own.
The intent for the code below is to copy cell "D5" from every sheet in workbook and then paste all the data in workbook "Data", range D4:D300 (the range is pretty broad so it will have more cell available than cells copied). The problem is that the code below is not working. All the code is doing is coping cell D5 from the first sheet over the range indicated (D4:D300). Basically copying the same value 266 times. Any help is highly appreciated.
If there is a more elegant/efficient way to write this code, please advise.
Sub copycell()
Dim sh As Worksheet
Dim wb As Workbook
Dim DestSh As Worksheet
Dim LastRow As Long
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set DestSh = wb.Sheets("Data")
' Loop through worksheets that start with the name "20"
For Each sh In ActiveWorkbook.Worksheets
' Specify the range to copy the data
sh.Range("D5").Copy
' Paste copied range into "Data" worksheet in Column D
With DestSh.Range("D4:D300")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
Next
End Sub
You don't need to specify an end range -- just 'count' the number of sheets to determine the total # of values you'll need to add to the data tab. Also added in a check to see if you're on the Data worksheet so you don't copy the D5 value from Data again into a row in the same worksheet.
Sub copycell()
Dim sh As Worksheet
Dim wb As Workbook
Dim DestSh As Worksheet
Dim i As Integer
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set DestSh = wb.Sheets("Data")
' Loop through worksheets that start with the name "20"
i = 4
For Each sh In ActiveWorkbook.Worksheets
If sh.Name = "Data" Then Exit Sub
sh.Range("D5").Copy
With DestSh.Range("d" & i)
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
i = i + 1
Next
End Sub
On each pass through your ActiveWorkbook.Worksheets loop, paste into the cell below the last cell in column D unless D4 is blank, in which case paste in D4. I'm assuming column D is completely blank before running the macro but if D3 has something in it you can do away with the .Range("D4") = "" test.
Sub copycell()
Dim sh As Worksheet
Dim wb As Workbook
Dim DestSh As Worksheet
Dim LastRow As Long
On Error GoTo GracefulExit:
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set wb = ThisWorkbook
Set DestSh = wb.Sheets("Data")
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> "Data" Then
sh.Range("D5").Copy
' Paste copied range into "Data" worksheet in Column D
' starting at D4
With DestSh
If .Range("D4") = "" Then
With .Range("D4")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
End With
Else
With .Cells(.Cells(.Rows.Count, 4).End(xlUp).Row + 1, 4)
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
End With
End If
End With
End If
Application.CutCopyMode = False
Next
GracefulExit:
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
If Err <> 0 Then
MsgBox "An unexpected error no. " & Err & ": " _
& Err.Description & " occured!", vbExclamation
End If
End Sub
if you are more concerned about values, then a more concise code could be the following:
Option Explicit
Sub copycell()
Dim sh As Worksheet
Dim iSh As Long
With ThisWorkbook
ReDim dataArr(1 To .Worksheets.Count - 1)
For Each sh In .Worksheets
If sh.Name <> "Data" Then
iSh = iSh + 1
dataArr(iSh) = sh.Range("D5").Value
End If
Next
.Worksheets("Data").Range("D4").Resize(.Worksheets.Count - 1).Value = Application.Transpose(dataArr)
End With
End Sub
where you first store all sheets D5 cell values into an array and then write them in one shot into Data worksheet

Excel VBA running out of Memory but there is plenty of memory

i have this code:
Sub reportCreation()
Dim sourceFile As Variant
Dim wbSource As Workbook
Dim wbDest As Workbook
Dim sourceSheet As Worksheet
Dim destSheet As Worksheet
Dim rng As Range
Dim i As Long
Dim NValues As Long
If sourceFile = False Then
MsgBox ("Select the MyStats file that you want to import to this report")
sourceFile = Application.GetOpenFilename
Set wbSource = Workbooks.Open(sourceFile)
Set sourceSheet = wbSource.Sheets("Test Dummy Sheet")
Set rng = sourceSheet.Range("A:N")
rng.Copy
Set wbDest = ThisWorkbook
Set destSheet = wbDest.Sheets("MyStats")
destSheet.Range("A1").PasteSpecial
Application.CutCopyMode = False
wbSource.Close
End If
NValues = destSheet.Cells(destSheet.Rows.Count, 2).End(xlUp).Row
With destSheet
For i = 6 To NValues
' Cells(i, 3).NumberFormat = "0"
With Cells(i, 3)
.Value = Cells.Value / 1000000
.NumberFormat = "0.00"
End With
Next i
End With
End Sub
the code runs fine for the IF Statement part which is a simple cop and paste sort of scenario but then once the WS has been copied to the new WB i need column 3 to devide any cell in that is larger than 1M by 1M and as soon as the code finds the first cell with a value of over 1M i get an error message "Runtime Error 7, system out of memory" but i still have 2GB left of memory so this does not seem to be your tipycal out of mem issue where i need to close a few applications and it will run because it just does not.
i am wondering if there is an issue with my code?
some of the sample values that the code will look are:
16000000
220000
2048000
230000
16000000
230000
16000000
you may want to adopt a different approach like follows (see comments)
Option Explicit
Sub reportCreation()
Dim sourceFile As Variant
Dim sourceSheet As Worksheet
Dim tempCell As Range
sourceFile = Application.GetOpenFilename(Title:="Select the MyStats file that you want to import to this report", _
FileFilter:="Excel Files *.xls* (*.xls*),") '<-- force user to select only excel format files
If sourceFile = False Then Exit Sub '<-- exit if no file selected
Set sourceSheet = TryGetWorkSheet(CStr(sourceFile), "Test Dummy Sheet") '<-- try and get the wanted worksheet reference in the chosen workbook
If sourceSheet Is Nothing Then Exit Sub '<-- exit if selected file has no "Test Dummy Sheet" sheet
With sourceSheet '<-- reference your "source" worksheet
Intersect(.UsedRange, .Range("A:N")).Copy
End With
With ThisWorkbook.Sheets("MyStats") '<-- reference your "destination" worksheet
.Range("A1").PasteSpecial
Application.CutCopyMode = False
sourceSheet.Parent.Close
Set tempCell = .UsedRange.Cells(.UsedRange.Rows.Count + 1, .UsedRange.Columns.Count) '<-- get a "temporary" cell not in referenced worksheet usedrange
tempCell.Value = 1000000 'set its value to the wanted divider
tempCell.Copy ' get that value into clipboard
With .Range("C6:C" & .Cells(.Rows.Count, 2).End(xlUp).Row) '<-- reference cells in column "C" from row 6 down to last not empty one in column "B"
.PasteSpecial Paste:=xlValues, Operation:=xlPasteSpecialOperationDivide '<-- divide their values by clipboard content
.NumberFormat = "0.00" '<-- set their numberformat
End With
tempCell.ClearContents '<-- clear the temporary cell
End With
End Sub
Function TryGetWorkSheet(wbFullName As String, shtName As String) As Worksheet
On Error Resume Next
Set TryGetWorkSheet = Workbooks.Open(wbFullName).Sheets("Test Dummy Sheet")
End Function

Delete multi Rows in Workbook2 depending on cell values in Workbook1

I need VBA code that will open Workbook2 depending on value of a cell in Workbook1 (A1).
In B:B column (Workbook1) there are values, if these values are the same as those available in A:A column (Workbook2) delete entire row that contains the same values in (Workbook2).
Can anyone help me to create the code?
i tried this one .....
Private Sub CommandButton1_Click()
Dim WB1, WB2 As Workbook
Dim WS1, WS2 As Worksheet
Set WB1 = ThisWorkbook
CSN = Cells(1, 1)
Set WB2 = Workbooks.Open("C:\Users\Basel\Desktop\" & CSN & "")
Set WS1 = WB1.Worksheets("sheet1")
Set WS2 = WB2.Worksheets("Sheet1")
LastRow1 = WB1.WS1.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
LastRow2 = WB2.WS2.Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To 20
If WB1.WS1.Cells(i, 2).Value = WB2.WS2.Cells(i, 1).Value Then
WB2.WS2.Cells(i, 1).EntireRow.Delete
End If
Next i
End Sub
Assuming the following:
1) you have created two workbook objects called WorkBook1 and WorkBook2
2) you are comparing column "A" in both books with the sheet called "sheet1"
Dim WB1sheet As Worksheet
Dim WB2sheet As Worksheet
Dim cell As Range
Dim cell2 As Range
Set WB1sheet = WorkBook1.Sheets("sheet1")
Set wb2sheet = Workbook2.Sheets("sheet1")
'Loop through colum A
For Each cell In WB1sheet.Range("a1", "a1000000")
' for each loop through the other sheet
If cell = "" Then
Exit For
End If
For Each cell2 In wb2sheet.Range("a1", "a1000000")
If cell = cell2 Then
cell2.ClearContents
Exit For
End If
Next cell2
Next cell
End Sub
This will just leave a blank cell not delete the row, it is more tricky to delete the row because the for each loop will get out of sink and miss rows.
If you need the row removed not just cleared then the easy fix is to do a sort on the column afterwards and the blanks will all move to the bottom. Just record the sort using macro record.
Good luck
thanks really i made some modification on the code but it works.
Private Sub CommandButton1_Click()
Dim WB1, WB2 As Workbook
Dim WS1, WS2 As Worksheet
Dim CELL1 As Range
Dim CELL2 As Range
CSN = Cells(1, 1)
Set WB1 = ThisWorkbook
Set WB2 = Workbooks.Open("C:\Users\Basel\Desktop\" & CSN & "")
Set WS1 = WB1.Worksheets("sheet1")
Set WS2 = WB2.Worksheets("Sheet1")
For Each CELL1 In WS1.Range("B1", "B10")
If CELL1 = "" Then
Exit For
End If
For Each CELL2 In WS2.Range("A1", "A10")
If CELL1 = CELL2 Then
CELL2.EntireRow.Delete
Exit For
End If
Next CELL2
Next CELL1
WB2.Save
WB2.Close
Range("B:B").ClearContents
End Sub`
`

Copy data from one worksheet to another based on column

I am trying to write a macro that will copy data from one worksheet to another based on column headers. Lets say in ws1 there are three columns: "product", "name", "employer" and the ws2: "product", "name", "region".
So i want the macro to do all the copying as in my original file i have over 100 column headers and it will be very time consuming for to do it myself.
I have written two macros without succes. VBA is something I cant understand for quite some time. but still managed to write something, hope you can tell me if i am going in the right direction.
this is v1
Sub Copy_rangev1()
Dim Ws1 As Worksheet, Ws2 As Worksheet
Dim SourceRange As Range, CopyRange As Range
Dim lastrow As Long
Dim i As Integer
Set Ws1 = ThisWorkbook.Worksheets("Sheet1")
Set Ws2 = ThisWorkbook.Worksheets("sheet2")
lastrow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Set SourceRange = Ws2.Range("A1").CurrentRegion
Set CopyRange = Ws1.Range("A1").CurrentRegion
For i = 1 To lastrow
If SourceRange.Cells(i, 1).Value = CopyRange.Cells(i, 1) Then
SourceRange.Cells(i + 1 & lastrow, 1).Copy Destination:=CopyRange.Range("a" & lastrow)
End If
Next i
End Sub
this v2:
Sub Copyrangev2()
Dim SourceRange As Worksheet
Dim CopyRange As Worksheet
Dim lastrow As Integer
Set SourceRange = Worksheets("Sheet2")
Set CopyRange = ThisWorkbook.Worksheets("sheet1")
Dim i As Integer
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To 100
If SourceRange.Range(1, i).Value = CopyRange.Range(1, i) Then
SourceRange.Range(1, i).Offset(1, 0).Copy Destination:=CopyRange.Range(1, i)
End If
Next i
End Sub
My code is a mess, but if you want me to provide any more details leave a comment, i dont expect you to given a fully workable code, a good explanation and few suggestions will do. Thanks
How about this? This code works as follows
Iterate across each column header in ws1 and see if a matching
header exists in ws2
If a match is found, copy the column contents across to the relevant column in ws2
This will work irrespective of column order. You can change the range references to suit.
Sub CopyHeaders()
Dim header As Range, headers As Range
Set headers = Worksheets("ws1").Range("A1:Z1")
For Each header In headers
If GetHeaderColumn(header.Value) > 0 Then
Range(header.Offset(1, 0), header.End(xlDown)).Copy Destination:=Worksheets("ws2").Cells(2, GetHeaderColumn(header.Value))
End If
Next
End Sub
Function GetHeaderColumn(header As String) As Integer
Dim headers As Range
Set headers = Worksheets("ws2").Range("A1:Z1")
GetHeaderColumn = IIf(IsNumeric(Application.Match(header, headers, 0)), Application.Match(header, headers, 0), 0)
End Function
Sub CustomColumnCopy()
Dim wsOrigin As Worksheet
Dim wsDest As Worksheet
Dim rngFnd As Range
Dim rngDestSearch As Range
Dim CalcMode As Long
Dim ViewMode As Long
Dim cel As Range
Dim rownum As Range
Set wsOrigin = Sheets("Sheet1")
Set wsDest = Sheets("Sheet2")
Const ORIGIN_ROW_HEADERS = 1
Const DEST_ROW_HEADERS = 1
If ActiveWorkbook.ProtectStructure = True Or _
wsOrigin.UsedRange.Parent.ProtectContents = True Then
MsgBox "Sorry, not working when the workbook or worksheet is protected", _
vbOKOnly, "Copy to new worksheet"
Exit Sub
End If
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
.EnableEvents = False
End With
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
ActiveSheet.DisplayPageBreaks = False
For Each rownum In wsOrigin.UsedRange
Set rngDestSearch = Intersect(wsDest.UsedRange, wsDest.Rows(DEST_ROW_HEADERS))
For Each cel In Intersect(wsOrigin.UsedRange, wsOrigin.Rows(ORIGIN_ROW_HEADERS))
On Error Resume Next
Set rngFnd = rngDestSearch.Find(cel.Value)
If Not rngFnd Is Nothing Then
wsDest.Cells(rownum.Cells.row, rngFnd.Column).Value = wsOrigin.Cells(rownum.Cells.row, cel.Column).Value
End If
On Error GoTo 0
Set rngFnd = Nothing
Next cel
Next rownum
ActiveWindow.View = ViewMode
Application.GoTo wsDest.Range("A1")
With Application
.ScreenUpdating = True
.EnableEvents = True
.Calculation = CalcMode
End With
Dim keyRange As Range
Set keyRange = Range("A1")
wsDest.Range("A" & LastRow(wsDest) + 1).Sort Key1:=keyRange, Header:=xlYes
End Sub