I already have a working macro that is transposing 5 rows into columns and append them after the last column.
The problem is that I need a long format so basically I want to automate the filling up, with the same data, until the end of data (basically the last row). I have 600 files and all these files have a different number of rows.
Sub LoopFiles()
Dim xFd As FileDialog
Dim xFdItem As Variant
Dim xFileName As String
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show = -1 Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
xFileName = Dir(xFdItem & "*.xls*")
Do While xFileName <> ""
With Workbooks.Open(xFdItem & xFileName)
'your code here
Range("A2:B6").Select
Selection.Copy
Range("I10").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Rows("1:8").Select
Application.CutCopyMode = False
Selection.Delete Shift:=xlUp
With Sheets("Calculated Saccades")
.Range("I3").AutoFill .Range("I4:I" & .Cells(.Rows.Count, "A").End(xlUp).Row)
End With
ActiveWorkbook.Save
ActiveWorkbook.Close
End With
xFileName = Dir
Loop
End If
End Sub
The With Sheets is returning an error. Any ideas? Thank you so very much!
You're already inside a With...End With block (With Workbooks.Open(xFdItem & xFileName) - this loops through workbooks if you select more than one in the File Open dialog box); you can't nest these.
You can simply replace
With Sheets("Calculated Saccades")
.Range("I3").AutoFill .Range("I4:I" & .Cells(.Rows.Count, "A").End(xlUp).Row)
End With
with:
Sheets("Calculated Saccades").Range("I3").AutoFill
Sheets("Calculated Saccades").Range("I4:I" & .Cells(.Rows.Count, "A").End(xlUp).Row)
You should also read How to avoid using Select in Excel VBA.
Related
as all i have a repeating work which i need to do on daily basis.
as i am a complete noob and my complete macro list which i have created is by reading here maybe you could help me out with one macro
is there a possiblity the macro from below to change that it will apply for all already open workbooks ?
Sub copyDown()
Dim myCount As Double
myCount = WorksheetFunction.CountA(Range("B:B"))
Range("ab2:ad" & myCount).FillDown
End Sub
Sub columnA()
Dim myfirstRow, myLastrow As Integer
myfirstRow = WorksheetFunction.CountA(Range("A:A")) + 1
myLastrow = WorksheetFunction.CountA(Range("B:B"))
Range("a" & myfirstRow & ":a" & myLastrow).Formula = "=TODAY() - 1"
Range("a" & myfirstRow & ":a" & myLastrow).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
End Sub
both sub i need to do in 5 files where each file have 2 specific sheets
in theory i know i could arrange it a bit different but my original macro have around 1600 lines and i am afraid to touch the running macro which i have build now for 2weeks :S
thank you all
This is how to create a separate sub that will find each workbook then call your original sub, passing it the worksheet it should work on.
I've only done it for "CopyDown", but it's exactly the same process.
Option Explicit
Sub Iterate_Workbooks()
Dim WB As Workbook
For Each WB In Application.Workbooks
' This is a way to exclude open workbooks from your search
' OR remove the "not" to include withbooks with only certain
' text in their name. "*" is wildcard, see some examples:
'If Not WB.Name Like "Master*" Then
'If WB.Name Like "FillerBook # *" Then
If Not WB.Name Like "*.xlsm" Then
Call copyDown(WB.Worksheets(1))
End If
Next WB
End Sub
Sub copyDown(WS As Worksheet)
Dim myCount As Double
With WS
myCount = WorksheetFunction.CountA(.Range("B:B"))
.Range("ab2:ad" & myCount).FillDown
End With
End Sub
You can create a function that would go through all the open workbooks and from each work book it will go through all the sheets and match the name of the sheets to call your subroutines columnA and copyDown by passing the sheet reference, hope this helps!
Sub ProcessAllWorkbooks()
Dim WB As Workbook, WS As Worksheet
For Each WB In Workbooks
For Each WS In WB.Sheets
If UCase(WS.Name) = "WHATEVER_NAME_OF_COPY_DOWN_SHEET_IN_UPPERCASE" Then
Call copyDown(WS)
ElseIf UCase(WS.Name) = "WHATEVER_NAME_OF_COLUMNa_SHEET_IN_UPPERCASE" Then
Call columnA(WS)
End If
Next
Next
End Sub
Sub copyDown(processWS As Worksheet)
Dim myCount As Double
With processWS
.Activate
.Range("B1").Select
myCount = WorksheetFunction.CountA(Range("B:B"))
Range("ab2:ad" & myCount).FillDown
End With
End Sub
Sub columnA(processWS As Worksheet)
Dim myfirstRow, myLastrow As Integer
With processWS
.Activate
.Range("A1").Select
myfirstRow = WorksheetFunction.CountA(Range("A:A")) + 1
myLastrow = WorksheetFunction.CountA(Range("B:B"))
Range("a" & myfirstRow & ":a" & myLastrow).Formula = "=TODAY() - 1"
Range("a" & myfirstRow & ":a" & myLastrow).Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
End With
End Sub
Can someone please let me know why my code is not pasting anything from my source data to my destination file?
The objectives of this code are to select rows that satisfy certain criteria, copy-pastes it into another workbook, The code is shown below:
Sub Copy_Source_LRE()
Dim LastRow As Integer, i As Integer, erow As Integer
Workbooks.Open _
"C:\Users\sjiang\OneDrive - Canada Pension Plan Investment Board\Desktop\IOA Exposure\AAPAF_strategy_loadings_2019-04-01_2020-04-01 (2).csv"
Worksheets("AAPAF_strategy_loadings_2019-04").Activate
Set sht = ActiveSheet
'Workbooks("AAPAF_strategy_loadings_2019-04-01_2020-04-01 (2).csv").Sheets("AAPAF_strategy_loadings_2019-04").Activate
LastRow = sht.Cells(sht.Rows.Count, "B").End(xlUp).Row
For i = 2 To LastRow
For Each d In Array("4/1/2019", "5/1/2019", "6/3/2019", "7/1/2019", "8/1/2019", "9/2/2019", _
"10/1/2019", "11/1/2019", "12/2/2019", "1/2/2020", "2/3/2020", "3/2/2020")
If Cells(i, 2) = d And Cells(i, 3) = "Real Estate" And Cells(i, 4) = "Listed Real Estate" And Cells(i, 5) = "AAPAF_SA" Then
Range(Cells(i, 2), Cells(i, 12)).Select
Selection.Copy
Workbooks.Open _
"C:\Users\sjiang\OneDrive - Canada Pension Plan Investment Board\Desktop\IOA Exposure\pull data.xlsm"
Worksheets("Sheet1").Select
erow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
ActiveSheet.Cells(erow, 1).Select
ActiveSheet.Paste
ActiveWorkbook.Save
'ActiveWorkbook.Close
End If
Next d
Next i
Application.CutCopyMode = False
End Sub
This is a really easy and basic way that I use all the time to copy data into new workbooks. In this example I'm copying a named range called "MasterData" into a new blank workbook. Then I save that new book with a password and re-activate the current workbook.
Dim newfilename As String
newfilename = "/Users/" & userName & "/Desktop/savedWorkbook.xlsx"
Dim NewBook As Workbook
Set NewBook = Workbooks.Add
ThisWorkbook.Activate
Sheets("Datasheet").Select
Range("MasterData").Copy
NewBook.Activate
NewBook.Sheets(1).Select
Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
NewBook.SaveAs Filename:=newfilename, Password:="examplepassword", AccessMode:=xlExclusive, ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges
NewBook.Close (True)
ThisWorkbook.Activate
I've redone the code for you as the major problem was related to a loop that is not really necessary. The best/fast way to apply those criteria and extract the data is using a filter to apply them, so copy the visible cells without the hidden (unmatching) lines and then open the second file where you need to past info, find next blank line below selection and paste all lines at once.
I'm pasting the code below (with comments) and also saved a zip file with 3 files (code, info, database) that might reflect your working files, link below.
VBS code:
Sub Copy_Source_LRE()
Dim LastRow As Integer, i As Integer, erow As Integer
Workbooks.Open ThisWorkbook.Path & "\" & "Wks1.xlsx" 'change the path and name here
Worksheets(1).Activate
Set sht = ActiveSheet
LastRow = Range("a1").SpecialCells(xlCellTypeLastCell).Row
datar = Range(Cells(LastRow, 12), Cells(1, 1)).Address 'data range
Range(datar).Select
Selection.AutoFilter 'create a filter,then use the criteria you need
ActiveSheet.Range(datar).AutoFilter Field:=2, Criteria1:= _
Array("4/1/2019", "5/1/2019", "6/3/2019", "7/1/2019", "8/1/2019", "9/2/2019", _
"10/1/2019", "11/1/2019", "12/2/2019", "1/2/2020", "2/3/2020", "3/2/2020"), Operator:=xlFilterValues 'your dates array can be update here
ActiveSheet.Range(datar).AutoFilter Field:=3, Criteria1:="Real Estate", Operator:=xlAnd
ActiveSheet.Range(datar).AutoFilter Field:=4, Criteria1:="Listed Real Estate", Operator:=xlAnd
ActiveSheet.Range(datar).AutoFilter Field:=5, Criteria1:="AAPAF_SA", Operator:=xlAnd
Range(datar).Offset(1, 0).Resize(Range(datar).Rows.Count - 1, Range(datar).Columns.Count).Select 'resize selection to remove the header
Selection.SpecialCells(xlCellTypeVisible).Select 'select visible cells only
Selection.Copy
Workbooks.Open ThisWorkbook.Path & "\" & "Wks2.xlsx" 'change the path and name here
Worksheets("Sheet1").Select
Range("A1").End(xlDown).Offset(1, 0).Select 'goes to the last row on column A the goes another one - 1st empty
ActiveSheet.Paste
ActiveWorkbook.Save
ActiveWorkbook.Close SaveChanges:=True 'close and save your database
Application.CutCopyMode = False
ActiveWorkbook.Close SaveChanges:=False 'close without saving your csv file
End Sub
link to files/code: https://drive.google.com/file/d/1zL_TwclHR4lrNhKB1xODGAmliPHM1r3K/view?usp=sharing
If the solution matches you need please consider as solution. Regards!
I have complied the below code for creating a separate bank payment sheet, everything is working fine but it is not deleting the rows of the cells whose value is "Delete" in column "E".
i have also observed while debugging that sometimes it deletes and sometimes it don't.
but now it is not deleting at all.
where I'm going wrong?
Sub Create_Bank_Sheet()
Dim fname As String
Dim path As String
Dim varResponse As Variant
Application.DisplayAlerts = False
varResponse = MsgBox("Select 'Yes' or 'No' File will be Saved at : " & Range("c43").Value, vbYesNo, "Are you sure you want to SaveAs this Sheet?")
If varResponse <> vbYes Then Exit Sub
Sheets("Bank Sheet for Payment").Select
path = Sheets("Command Center").Range("c43")
fname = Sheets("Command Center").Range("c42")
ThisWorkbook.Sheets("Bank Sheet for Payment").Copy
Application.ActiveWorkbook.SaveAs Filename:=path & "\" & fname, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
Cells.Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Dim c As Range
Dim SrchRng As Range
Dim SrchStr As String
Set SrchRng = ActiveSheet.Range("e4", ActiveSheet.Range("e65536").End(xlUp))
SrchStr = "Delete"
Do
Set c = SrchRng.Find(SrchStr, LookIn:=xlValues)
If Not c Is Nothing Then c.EntireRow.Delete
Loop While Not c Is Nothing
ActiveWorkbook.Save
MsgBox ("File saved in " & path)
ActiveWorkbook.Close
Application.DisplayAlerts = True
End Sub
You're not setting your SrchRng correctly.
Try
Set SrchRng = ActiveSheet.Range("E4:E" & ActiveSheet.Range("E65536").End(xlUp).Row)
I have a task to add workbook name into all worksheet's first column hence i need to have a macro and below is a draft of the same
Sub InsertWorkbookName()
Path = "C:\Users\mechee69\Download\"
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Columns("A:A").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Range("A1").Select
ActiveCell.SpecialCells(xlLastCell).Select
Application.Goto Range("A" & ActiveCell.Row), True
ActiveCell.Select
ActiveCell.FormulaR1C1 = _
"=RIGHT(LEFT(CELL(""filename""),FIND(""."",CELL(""filename""),FIND(""["",CELL(""filename""),1))-1),FIND(""."",CELL(""filename""),FIND(""["",CELL(""filename""),1))-FIND(""["",CELL(""filename""),1)-1)"
Application.Goto Range("A" & ActiveCell.Row), True
ActiveCell.Select
Selection.Copy
Range(Selection, Selection.End(xlUp)).Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
ActiveWorkbook.Save
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
Try this
Sub WorkbookName()
Dim wbk As Workbook
Dim strFilename As String
Dim strPath As String
Dim wc As Worksheet
Dim lngLastR As Long
Dim lngSecurity as Long
lngSecurity = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityLow
strPath = "[Full Folder Path]"
strFilename = Dir(strPath & "*.xlsx")
Do While strFilename <> ""
Set wbk = Workbooks.Open(strPath & strFilename)
For Each ws In wbk.Worksheets
lngLastR = ws.Range("A" & Rows.Count).End(xlUp).Row
ws.Range("A:A").Insert Shift:=xlToRight
ws.Range("A1:A" & lngLastR).Value = wbk.Name
Next
wbk.Save
wbk.Close False
strFilename = Dir
Loop
Application.AutomationSecurity = lSecurity
MsgBox ("Done")
End Sub
As a quick run through of what this code does.
'Dir' goes through a folder on a criteria, the criteria in this case being ".xlsx" this is to make sure it only opens xlsx files.
'Do While' is a form of loop, this will repeat all code between the "Do While" and the "Loop" until the condition is no longer true.
Once deciding on the file it opens the workbook and remembers it as a variable, this is so I can reference it's name more easily.
I then find the last used row by starting at the bottom cell of row "A" and going up until there is data in a cell. There is a write up on this on stack overflow (Link: Error in finding last used cell in VBA)
I then insert a row to the left pushing the data to the right and set the value of all cells in row 'A' in the used ranged to the name of the workbook using the workbooks '.Name' function.
I then save and close the workbook before using the 'Dir' to the next file name ready to start the process again, this will repeat for all files and give you a message box saying "Done" once it has completed them all.
If you have any questions let me know
Edited to include a bypass for protected view
So this Macro will open Excel Files in a Folder with a specific format, then it prints the workbookname in A1 in every sheet of that file. It ignores the master, if its in the same folder.
Sub WorkbookName()
Dim wbk As Workbook
Dim Filename As String
Dim Path As String
Dim lastRow As Long
Dim lSecurity As Long
On Error Resume Next
Path = "C:\Users\User\Desktop\Files\" 'Folder of your Files
Filename = Dir(Path & "*.xlsx") 'Format of your files
Do While Filename <> "" And Filename <> "Master.xlsm" 'Dont Open MasterFile
Set wbk = Workbooks.Open(Path & Filename)
lSecurity = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityLow
For Each ws In wbk.Worksheets
With ws
.Range("A1").EntireColumn.Insert
lastRow = .Cells(Rows.Count, 2).End(xlUp).Row
.Range(Cells(1, 1), Cells(lastRow, 1)).Value = ActiveWorkbook.Name
End With
Application.AutomationSecurity = lSecurity
Next ws
wbk.Close True
Filename = Dir
Loop
End Sub
I am a Visual Basic newbie. From hints on the web, I pieced together an Excel macro that does several things, including concatenating first and last name, in a loop, to make a new column with those joined. Half the time it works great, half the time I end up with no space between the first and last name. (In those cases, closing, re-opening, and re-running almost always works.) Is this a timing issue? I'll put in the whole macro but it's the Do While loop near the top that I think is the problem.
Thanks for any help.
Sub WholeThing()
'
' WholeThing Macro
Application.ScreenUpdating = False
ActiveSheet.Name = "original"
Rows("1:1").Delete Shift:=xlUp
Do While ActiveCell <> "" 'Loops until the active cell is blank.
ActiveCell.Offset(0, 0).FormulaR1C1 = _
ActiveCell.Offset(0, 1) & " " & ActiveCell.Offset(0, 2)
ActiveCell.Offset(1, 0).Select
Loop
Application.Wait (Now + TimeValue("0:00:02"))
Sheets.Add After:=Sheets(Sheets.Count)
Sheets.Add After:=Sheets(Sheets.Count)
Sheets.Add After:=Sheets(Sheets.Count)
Sheets.Add After:=Sheets(Sheets.Count)
Sheets.Add After:=Sheets(Sheets.Count)
Sheets.Add After:=Sheets(Sheets.Count)
Sheets("Original").Activate
ActiveWindow.WindowState = xlNormal
Application.CutCopyMode = False
Application.DisplayAlerts = False
Range("A1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet6").Range("A1")
Range("D1").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet6").Range("B1")
Sheets("Original").Activate
ActiveWindow.WindowState = xlNormal
Application.CutCopyMode = False
Application.DisplayAlerts = True
Columns("Y:Y").Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet2").Range("A1")
Columns("Z:Z").Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet3").Range("A1")
Columns("AA:AA").Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet4").Range("A1")
Columns("AB:AB").Copy
ActiveSheet.Paste Destination:=Worksheets("Sheet5").Range("A1")
Application.DisplayAlerts = False
Sheets("Sheet5").Activate
ActiveWorkbook.SaveAs Filename:="Y:\Addrs_DL", FileFormat:=xlCSV, _
CreateBackup:=False
Sheets("Sheet4").Activate
ActiveWorkbook.SaveAs Filename:="Y:\Addrs_D", FileFormat:=xlCSV, _
CreateBackup:=False
Sheets("Sheet3").Activate
ActiveWorkbook.SaveAs Filename:="Y:\Addrs_SL", FileFormat:=xlCSV, _
CreateBackup:=False
Sheets("Sheet2").Activate
ActiveWorkbook.SaveAs Filename:="Y:\Addrs_S", FileFormat:=xlCSV, _
CreateBackup:=False
Sheets("Sheet6").Activate
ChDir "Y:\"
Application.ScreenUpdating = True
ActiveWorkbook.SaveAs Filename:="Y:\NAME-ADR.CSV", FileFormat:=xlCSV, _
CreateBackup:=False
' Application.Quit
' Application.ActiveWindow.Close SaveChanges:=False
' ActiveWorkbook.Close SaveChanges:=False
End Sub
By not using ActiveCell and working with your range directly, you can make your code more stable and more reliable.
Consider something like this (see notes about assumptions on range and cell references).
Dim ws as Worksheet
Set ws = ThisWorkbook.Sheets("original")
With ws
Dim lRow as Long
lRow = .Range("B" & .Rows.Count).End(xlup).Row 'assumes first name in column B
'assumes concatenated name goes in column A, starting at row 1 (and the first and last name are in B and C, respectively
.Range("A1:A" & lRow).FormulaR1C1 = "=RC[1] & "" "" & RC[2]"
'if you want to copy as values you can use this
.Range("A1:A" & lRow).Value = .Range("A1:A" & lRow).Value
End With
You can also work with the same principles of working directly with the object later on in your code, like this:
'lRow would be the last row of data in the column (assumes same row for each column, based on dataset)
ws.Range("Y1:Y" & lRow).Copy Worksheets("Sheet2").Range("A1")
Doing this will save a lot of processing time as copying entire columns is very inefficient if it's not truly needed.
To do the concatenate, I had first to use this to get the number of the last row:
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
That enabled this loop to do the concatenation:
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("original")
With ws
For i = 1 To LastRow
Cells(i, 1) = Cells(i, 2) & " " & Cells(i, 3)
Next i
Then, for the second block (the "With ws" being still in effect):
Sheets("Original").Activate
Range("Y1:Y" & LastRow).Copy Worksheets("Sheet2").Range("A1")