i have a job which i need to merge 4 files together. May i know what if i have more files in coming future to merge, instead keying the "open workbook"code. What kind of method should i use? and yet meet the lowest line merge criteria as well. Below is the code i have attempt so far
Sub GetFile()
Dim Book1Path As Variant, Book2Path As Variant, Book3Path As Variant, Book4Path As Variant
Dim SourceWB As Workbook, DestWB As Workbook
Dim lRow As Long
Dim ws1, ws2, ws3, ws4 As Worksheet
Dim c3ll1, c3ll2, c3113, c3114, range1, range2, range3, range4 As Range
'## Open both workbook first:
Book1Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 1")
If Book1Path = False Then Exit Sub
Set SourceWB = Workbooks.Open(Book1Path)
Book2Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 2")
If Book2Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book2Path)
Book3Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 3")
If Book3Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book3Path)
Book4Path = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter 4")
If Book4Path = False Then Exit Sub
Set DestWB = Workbooks.Open(Book4Path)
'Copy.
With SourceWB.Sheets("Report")
lRow = .Cells(Rows.Count, 1).End(xlUp).Row
.Range("A2:F" & lRow).Copy
End With
'Active Merge Workbook
ThisWorkbook.Activate
'Paste.
Columns("A").Find("", Cells(Rows.Count, "A")).Select
Selection.PasteSpecial
'Active CWPI Topic 1 Assessment Workbook
SourceWB.Activate
'Copy.
With SourceWB.Sheets("Report")
lRow = .Cells(Rows.Count, 1).End(xlUp).Row
.Range("G2:G" & lRow).Copy
End With
'Active Merge Workbook
ThisWorkbook.Activate
'Paste.
Columns("G").Find("", Cells(Rows.Count, "G")).Select
Selection.PasteSpecial
Set ws1 = SourceWB.Sheets("Report")
Set ws2 = DestWB.Sheets("Report")
Set ws3 = DestWB.Sheets("Report")
Set ws4 = DestWB.Sheets("Report")
lastrow2 = ws2.Cells(Rows.Count, 1).End(xlUp).Row
Set range2 = ws2.Range("A2:A" & lastrow2)
lastrow1 = ws1.Cells(Rows.Count, 1).End(xlUp).Row
Set range1 = ws1.Range("A2:A" & lastrow1)
For Each c3ll2 In range2
a = 0
activerow2 = c3ll2.Row
For Each c3ll1 In range1
If c3ll1.Value = c3ll2.Value Then
activerow1 = c3ll1.Row
Cells(activerow1, "H") = ws2.Cells(activerow2, 3)
Cells(activerow1, "I") = ws2.Cells(activerow2, 4)
Cells(activerow1, "J") = ws2.Cells(activerow2, 5)
Cells(activerow1, "K") = ws2.Cells(activerow2, 6)
Cells(activerow1, "L") = ws2.Cells(activerow2, 7)
a = 1 'Username is found
Exit For
End If
Next c3ll1
If a = 0 Then 'If Username is not found print at end
lastrow1 = lastrow1 + 1
Cells(lastrow1, "A") = ws2.Cells(activerow2, 1)
Cells(lastrow1, "B") = ws2.Cells(activerow2, 2)
Cells(lastrow1, "H") = ws2.Cells(activerow2, 3)
Cells(lastrow1, "I") = ws2.Cells(activerow2, 4)
Cells(lastrow1, "J") = ws2.Cells(activerow2, 5)
Cells(lastrow1, "K") = ws2.Cells(activerow2, 6)
Cells(lastrow1, "L") = ws2.Cells(activerow2, 7)
End If
Next c3ll2
'Columns Width Autofit
ActiveSheet.Columns.AutoFit
With Application
Cells(.CountA(Columns("A:A")) + 1, 1).Select
.ScreenUpdating = True
.DisplayAlerts = False
SourceWB.Close
DestWB.Close
End With
End Sub
So...you're looking for a loop to open up more workbooks in an easy way? Right now, you are not opening 3 versions of DestWB like you think you are. You are instead overwriting DestWB each time you call...
Set DestWB = Workbooks.Open(BookXPath)
I would replace your three blocks that open the path, check the path, and then open the path to the workbook DestWB with the following:
'Create an array of paths, and a corresponding array of workbooks
Dim paths() As String, wbs() as Workbook
ReDim paths(3)
'ReDim wbs to the same as path so its easier to adjust in the future
ReDim wbs(UBound(paths))
'Set your paths, then loop through them to assign your workbooks
Dim x as Integer
For x = 1 To UBound(paths)
paths(x) = Application.GetOpenFilename(FileFilter:="Excel Files (*.XLS), *.XLS", Title:="Chapter " + CStr(x))
If paths(x) = "False" Then
Exit Sub
End If
Set wbs(x) = Workbooks.Open(paths(x))
Next x
You can use the same loop methodology to do the other tasks in this macro. You can also eliminate all your activating of the ThisWorkbook by setting it as a variable.
Dim thisWB as Workbook
Set thisWB = ThisWorkbook
This will in turn let you clean up this code...
Columns("A").Find("", Cells(Rows.Count, "A")).Select
Selection.PasteSpecial
Into this code...
thisWB.Sheets("SOMESHEET").Columns("A").Find("", Cells(Rows.Count, "A")).PasteSpecial
In general .Select and Selection should be avoided. Search around stackoverflow and Google, there are plenty of examples for both loops and eliminating .Select and Selection.
Related
i have started this code, which looks in worksheet PCrun for "yes" in cell D2 then then copies A1:C9 and paste as an image to worksheet PCexport starting at cell A1.
This works but there are a few more steps i am stuck on.
I would like it to move on to the next range of cells A10:C18 looking in cell D11 for a yes.
This needs to continue i.e
D2 - C1:C9
D11 - A10:C28
D20 - A19:C27
and so on adding 9 each time and coping if there is a yes in D and pasting as an picture to the next avalible cell in worksheet PCexport.
Sub CopyIf()
Dim LastRow As Long, i As Long, erow As Long
Dim wsStr As String
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook, wbM As Workbook
Dim C As Range
LastRow = Worksheets("PCexport").Range("A" & Rows.Count).End(xlUp).Row
Set wb = ActiveWorkbook
Set wsC = wb.Sheets("PCrun")
erow = wsC.Cells(Rows.Count, 1).End(xlUp).Row
Worksheets("PCrun").Activate
For i = 1 To LastRow
If wsC.Cells(2, 4).Value = "YES" Then
erow = erow + 9
wsC.Range(wsC.Cells(1, 1), wsC.Cells(9, 3)).CopyPicture 'avoid select
Sheets("PCexport").Range("A1").PasteSpecial
End If
Next i End Sub
Some i came up with this.
`
Sub CopyIf()
Set Ask = Worksheets("PCrun").Range("$d2")
Set CP = Worksheets("PCrun").Range("a1:c9")
Set Give = Worksheets("PCexport").Range("$a1")
Worksheets("PCrun").Activate
For j = 0 To 135 Step 9
Set CPvar = CP.Offset(j, 0)
Set Askvar = Ask.Offset(j, 0)
Set Givevar = Give.Offset(j, 0)
If Askvar.Value = "YES" Then
CPvar.CopyPicture
With Sheets("PCexport").Range("A" & Rows.Count).End(xlUp).Offset(1).PasteSpecial
End With
End If
Next j
End Sub`
Try incorporating your for-step in your cell referencing
Sub CopyIf()
Dim LastRow As Long, i As Long, erow As Long
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook
Dim C As Range
LastRow = Worksheets("PCexport").Range("A" & Rows.Count).End(xlUp).Row
Set wb = ActiveWorkbook
Set wsC = wb.Sheets("PCrun")
erow = wsC.Range("A" & Rows.Count).End(xlUp).Row + 1
Worksheets("PCrun").Activate
For i = 0 To LastRow -1 Step 9
If wsC.Cells(2 + i, 4).Value = "YES" Then
wsC.Range(wsC.Cells(1 + i, 1), wsC.Cells(9 + i, 3)).CopyPicture 'avoid select 'not sure why you're opting for pictures
Sheets("PCexport").Range("A" & erow).PasteSpecial
erow = erow + 9 'you were filling your erow but weren't using it
End If
Next i
End Sub
This seems to do all i need.
{Sub CopyIf()
Dim i As Long, erow As Long
Dim wsStr As String
Dim ws As Worksheet, wsC As Worksheet
Dim wb As Workbook, wbM As Workbook
Dim C As Range}
Set Ask = Worksheets("PCrun").Range("$d2")
Set CP = Worksheets("PCrun").Range("a1:c9")
Set Give = Worksheets("PCexport").Range("$a1")
Set Take = Worksheets("PCexport").Range("a1")
Worksheets("PCrun").Activate
For j = 0 To 135 Step 9
Set CPvar = CP.Offset(j, 0)
Set Askvar = Ask.Offset(j, 0)
Set GiVevar = Give.Offset(j, 0)
Set Takevar = Take.Offset(j, 0)
If Askvar.Value = "YES" Then
CPvar.CopyPicture
GiVevar.Offset.PasteSpecial
Else
Takevar.Value = 1
End If
Next j
Worksheets("PCexport").Activate
Set Check = Worksheets("PCexport").Range("a1")
Set Take2 = Worksheets("PCexport").Range("A1:C9")
For k = 0 To 135 Step 9
Set Checkvar = Check.Offset(k, 0)
Set Take2var = Take2.Offset(k, 0)
If Checkvar.Value = "1" Then
Take2var.Delete
End If
Next k
I have this little code that replaces the letters from a table like this (find the left string and replace it with the right string):
However it takes a great amount of time to do all the replacements in the sheets I have (just 2). Nearly 10 seconds. Is there a way to speed this up pls? Many thanks for taking the time!!
Dim sht As Worksheet
Dim fndList As Integer
Dim rplcList As Integer
Dim tbl As ListObject
Dim myArray As Variant
Dim ReplaceCount As Long
Set sht = Sheets("Sheet1")
Application.ScreenUpdating = False
'Create variable to point to your table
Set tbl = Worksheets("Sheet1").ListObjects("StringReplace")
'Create an Array out of the Table's Data
Set TempArray = tbl.DataBodyRange
myArray = Application.Transpose(TempArray)
'Designate Columns for Find/Replace data
fndList = 1
rplcList = 2
'Loop through each item in Array lists
For x = LBound(myArray, 1) To UBound(myArray, 2)
'Loop through each worksheet in ActiveWorkbook (skip sheet with table in it)
For Each sht In ActiveWorkbook.Worksheets
If sht.Name <> tbl.Parent.Name Then
sht.Cells.Replace What:=myArray(fndList, x), Replacement:=myArray(rplcList, x), _
LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
End If
Next sht
Next x
Application.ScreenUpdating = True
Replace Strings in Multiple Worksheets
The Code
Option Explicit
Sub replaceOddStrings()
Const WorksheetName As String = "Sheet1"
Const TableName As String = "StringReplace"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim Data As Variant: Data = wb.Worksheets(WorksheetName) _
.ListObjects(TableName).DataBodyRange.Value
Dim ws As Worksheet
Dim i As Long
Application.ScreenUpdating = False
For Each ws In wb.Worksheets
If ws.Name <> WorksheetName Then
For i = 1 To UBound(Data, 1)
ws.UsedRange.Replace Data(i, 1), Data(i, 2), xlPart, , False, _
False, False, False
Next i
End If
Next ws
Application.ScreenUpdating = True
MsgBox "Strings replaced.", vbInformation, "Success"
End Sub
The goal is to look through Column A in all Sheets in the array. If "CASH" is found in a cell in Column A, replace Column D of that same row With "USD".
I am hitting an error with the array.range. I realize I can't declare it as is but not sure what to do from here. I will likely his a snag with the loop as well, open to suggestion there too.
Thanks
Sub test()
Dim Sht As Worksheet
Dim SCAFI, ILB, IILB, MMA, IMBD, SCAEQ, IMEQ, IREA, IMSC, ExclSecFI, ExclSecEQ As Worksheet
Dim FIFindCASH, FIFindCASHRng As Variant
Set FIFindCASHRng = Sheets(Array("SCA FI", "ILB", "IILB", "MMA", "IMBD", "Excluded Securities FI")).Range("A:A")
Set SCAFI = Sheets("SCA FI")
Set ILB = Sheets("ILB")
Set IILB = Sheets("IILB")
Set MMA = Sheets("MMA")
Set IMBD = Sheets("IMBD")
Set SCAEQ = Sheets("SCA EQ")
Set IMEQ = Sheets("IMEQ")
Set IREA = Sheets("IREA")
Set IMSC = Sheets("IMSC")
Set ExclSecFI = Sheets("Excluded Securities FI")
Set ExclSecEQ = Sheets("Excluded Securities EQ")
For Each Sht In FIFindCASHRng
If Cell.Value = "CASH" Then
Cell.Value.Offset(0, 3) = "USD"
End If
Next
End Sub
Test the next code, please:
Sub testIterateChangeVal()
Dim wb As Workbook, Sht As Worksheet, i As Long, lastRow As Long
Set wb = ActiveWorkbook 'use here the needed workbook
For Each Sht In wb.Worksheets
Select Case Sht.Name
Case "SCA FI", "ILB", "IILB", "MMA", "IMBD", "Excluded Securities FI"
lastRow = Sht.Range("A" & Rows.count).End(xlUp).Row
For i = 1 To lastRow
If Sht.Range("A" & i).value = "CASH" Then
Sht.Range("A" & i).Offset(0, 3) = "USD"
'or
'Sht.Range("D" & i).value = "USD"
End If
Next i
End Select
Next
End Sub
I have a master file having different account details. I am trying to make a code that will send a copy of the workbook after deleting unnecessary account details and mail it. It is working fine for one sheet but when I am using array for multiple sheets it is giving me object doesn't support method in this line of code ".DisplayPageBreaks = False".
Here is my code:
Sub Mail_Sheets_Array()
'Working in Excel 2000-2016
'For Tips see: http://www.rondebruin.nl/win/winmail/Outlook/tips.htm
Dim FileExtStr As String
Dim FileFormatNum As Long
Dim Sourcewb As Workbook
Dim Destwb As Workbook
Dim TempFilePath As String
Dim TempFileName As String
Dim OutApp As Object
Dim OutMail As Object
Dim sh As Worksheet
Dim TheActiveWindow As Window
Dim TempWindow As Window
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
Set Sourcewb = ActiveWorkbook
'Copy the sheets to a new workbook
'We add a temporary Window to avoid the Copy problem
'if there is a List or Table in one of the sheets and
'if the sheets are grouped
With Sourcewb
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("REC_INT", "REC_EXT")).Copy
End With
'Close temporary Window
TempWindow.Close
Set Destwb = ActiveWorkbook
'Determine the Excel version and file extension/format
With Destwb
If Val(Application.Version) < 12 Then
'You use Excel 97-2003
FileExtStr = ".xls": FileFormatNum = -4143
Else
'You use Excel 2007-2016
Select Case Sourcewb.FileFormat
Case 51: FileExtStr = ".xlsx": FileFormatNum = 51
Case 52:
If .HasVBProject Then
FileExtStr = ".xlsm": FileFormatNum = 52
Else
FileExtStr = ".xlsx": FileFormatNum = 51
End If
Case 56: FileExtStr = ".xls": FileFormatNum = 56
Case Else: FileExtStr = ".xlsb": FileFormatNum = 50
End Select
End If
End With
'Change all cells in the worksheets to values if you want
For Each sh In Destwb.Worksheets
sh.Select
With sh.UsedRange
.Cells.Copy
.Cells.PasteSpecial xlPasteValues
.Cells(1).Select
End With
Application.CutCopyMode = False
Destwb.Worksheets(1).Select
Next sh
'Save the new workbook/Mail it/Delete it
TempFilePath = Environ$("temp") & "\"
TempFileName = "Part of " & Sourcewb.name & " " & Format(Now, "dd-mmm-yy h-mm-ss")
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Dim Firstrow As Long
Dim Lastrow As Long
Dim Lrow As Long
Dim prow As Long
Dim r As Long
Dim x As Long
Dim y As Long
Dim CalcMode As Long
Dim ViewMode As Long
r = 0
With Application
CalcMode = .Calculation
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
'We use the ActiveSheet but you can replace this with
With Destwb.Sheets(Array("REC_INT", "REC_EXT"))
' With ActiveSheet
'We select the sheet so we can change the window view
.Select
'If you are in Page Break Preview Or Page Layout view go
'back to normal view, we do this for speed
ViewMode = ActiveWindow.View
ActiveWindow.View = xlNormalView
'Turn off Page Breaks, we do this for speed
.DisplayPageBreaks = False
'Set the first and last row to loop through
Firstrow = .UsedRange.Cells(1).Row
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
'We loop from Lastrow to Firstrow (bottom to top)
For Lrow = 9 To Lastrow Step 1
'We check the values in the A column in this example
With .Cells(Lrow, "C")
If Not IsError(.Value) Then
If Cells(Lrow, "D").Value = "Total" Then
GoTo y
End If
If .Value = Sheet1.Cells(2, 6) Then
r = r + 1
End If
If .Value <> Sheet1.Cells(2, 6) Then
If .Value = "" Then
r = 0
End If
prow = Lrow - r
If Cells(prow, "C").Value = Sheet1.Cells(2, 6) Then
r = r + 1
GoTo x
End If
.EntireRow.ClearContents
'This will delete each row with the Value "ron"
'in Column A, case sensitive.
x:
End If
End If
End With
Next Lrow
End With
ActiveWindow.View = ViewMode
With Application
.ScreenUpdating = True
.Calculation = CalcMode
End With
y:
Range(Cells(9, 3), Cells(Lrow, 3)). _
SpecialCells(xlCellTypeBlanks).EntireRow.Delete
'xxxxxxxxxxxxxxxxxx
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
With Destwb
.SaveAs TempFilePath & TempFileName & FileExtStr, FileFormat:=FileFormatNum
On Error Resume Next
With OutMail
.To = "hadi#siemens.com"
.CC = ""
.BCC = ""
.Subject = "This is the Subject line"
.Body = "Hi there"
.Attachments.Add Destwb.FullName
'You can add other files also like this
'.Attachments.Add ("C:\test.txt")
'.Send 'or use
.Display
End With
On Error GoTo 0
.Close savechanges:=False
End With
'Delete the file you have send
Kill TempFilePath & TempFileName & FileExtStr
Set OutMail = Nothing
Set OutApp = Nothing
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
You are trying to run a property only supported on a specified sheet, on multiple sheets at once. This is not supported, hence the error 438.
You can try to loop these sheets:
For Each ws In Destwb.Sheets
If ws.Name = "REC_INT" or ws.Name = "REC_EXT" then
Destwb.Worksheets(ws.Name).DisplayPageBreaks = False
End if
Next ws
I think you don't need to check for the sheets names, as you copy just the two of them into a new workbook.
In worksheet wsb,I am trying to copy column B and Column having ParName in header and pasting it to columns B & H respectively of worksheet wso. The problem is It's running only for first Item and also for the first matched value of i for that item and not for all the matched item-i values.
Dim ws, wsa, wsb, wsc, wso As Worksheet
Dim index1b, LastRow, MOLastRow, wsoLastRow As Long
Dim ColLtr1b As Variant
Dim MoNameArr
Set wsb = Workbooks(Y).Sheets("REF")
wsb.Activate
LastRow = GetLastRow(wsb, 2)
Arr = Array("Abc", "Def")
Set wso = Workbooks(W).Sheets("Output")
For Each Item In Arr
For i = 2 To LastRow
If Cells(i, 2).Value = Item Then
wsb.Activate
ParName = wsb.Cells(i, 3).Value
Set wsc = Workbooks(M).Sheets(Item)
wsc.Activate
index1b = Application.Match(ParName, wsc.Rows(1), 0)
If Not IsError(index1b) Then
ColLtr1b = Replace(wsc.Cells(1, index1b).Address(True, False), "$1", "")
MOLastRow = wsc.Cells(Rows.Count, 2).End(xlUp).Row
Range("B2:B" & GetLastRow(wsc, 2)).Copy
wso.Activate
wsoLastRow = GetLastRow(wso, 2)
Range("B" & wsoLastRow + 1).Select
ActiveSheet.Paste
wsc.Activate
Range(ColLtr1b & "2:" & ColLtr1b & GetLastRow(wsc, 2)).Copy
wso.Activate
Range("H" & wsoLastRow + 1).Select
ActiveSheet.Paste
End If
End If
Next i
Next Item
Declare your variables like this:
Dim ws As Worksheet, wsa As worksheet, wsb as Worksheet
Dim wsc as Worksheet, wso As Worksheet
Dim index1b as Long, LastRow as Long, MOLastRow as Long, wsoLastRow As Long
Then start debugging with pressing F8. It goes line by line and you may see where is the problem in the nested loop. It can be in one of these 3:
you need to write Trim(Cells(i, 2)) in the If Cells(i, 2).Value = Item Then condition;
you are not calculating LastRow correctly;
you have On Error Resume Next somewhere in your code and you are entering an error w/o noticing;