I have multiple excel files that are structured identically and are in a folder.
Each excel files data starts at d4 (multiple rows of data but all rows start on the subsequent d)
I need a macro to take the data from all the separate excel files in the folder and create a single new excel file of all the data from the separate excel files, structured like the following.
1.) Data from excel file one starts at a1 in the rollup file
2.) Data from excel file two appended underneath the data from the first excel file in the rollup file
3.) Repeat for all the excel files in the folder.
Thanks
Edit
I found this (I am sorry I don't remember where, I do remember it was not working)
I know very little about excel and vba (I mostly I work in php), I feel I am asking a lot with out being able to offer much help of my own toward getting what I need, I apologize for this.
I made two simple excel files and added a row of data in each and ran the macro in a excel file called Rollup.
I think the problem with this code is that it works in that in the Rollup excel file the cursor moves to the appropriate row as if it appended both files but there is no data showing up.
Sub extract()
Dim a, b, c, d, n, x As Integer
Dim f As String
Cells(2, 1).Select
f = Dir("C:\" & "*.xls")
Do While Len(f) > 0
ActiveCell.Formula = f
ActiveCell.Offset(1, 0).Select
f = Dir()
n = n + 1
Loop
x = Cells(Rows.Count, 1).End(xlUp).Row
d = 2
For a = 2 To x
Cells(d, 2) = Cells(a, 1)
For c = 1 To 20
b = 1
Cells(1, 1) = "='c:\[" & Cells(a, 1) & "]sheet1'!" & Chr(b + 64) & c
If Cells(1, 1) = "0" Then
Exit For
Else
For b = 3 To 6
Cells(d, b) = "='c:\[" & Cells(a, 1) & "]sheet1'!" & Chr(b + 64) & c
Next b
End If
d = d + 1
Next c
d = d + 1
Next a
End Sub
For a simple Rollup the following works, for more complicated need go here: http://msdn.microsoft.com/en-us/library/office/cc837974%28v=office.12%29.aspx
Sub test()
Dim myFile As String, sh As Worksheet, myRange As Range
Const MyPath = "C:\My path\" ' to be modified
Workbooks.Add 1 ' Add a new workbook
Set sh = ActiveWorkbook.ActiveSheet
myFile = Dir(MyPath & "*.xls")
Do While myFile <> ""
Workbooks.Open MyPath & myFile
Rows(1).Copy sh.Rows(1)
Set myRange = ActiveSheet.UsedRange
Set myRange = myRange.Offset(4).Resize(myRange.Rows.Count - 1) '(4) is how many rows to ignore befor coping data
myRange.Copy sh.Range("A65").End(xlUp).Offset(1)
Workbooks(myFile).Close False
myFile = Dir
Loop
End Sub
Related
I'm very new to writing Macros in Excel, and have done a bit of looking around to try and solve my problem, but I haven't found a solution yet that works.
I'm trying to write a Macro to do the following:
Copy data from Source A (sheet Daily_Inventory(m3), workbook Daily_Inventory_YYYYMMDD) based on column headings (so for example, I want to copy all the data under the column name "All activities").The number of rows of data in this row may increase/decrease.
And then I want to paste this data into Destination B (sheet Daily_Inventory(m3), workbook Daily_Inventory_Master) under the corresponding column name "MMDDYYYY".
The workbook Daily_Inventory_YYYYMMDD will be stored in my specify folder everyday in 365 days, then I have to copy information from it to another workbook with every single related column header daily. If column header is not exist, add new value (same datetime as source file) then paste.
Please help me in this case, I'd be extremely grateful for any help.
Many thanks!!!
This is all done in my head and not tested, but it shouldn't be far away:
bookName1 = "Daily_Inventory_YYYYMMDD.xlsx"
sheetName1 = "Daily_Inventory(m3)"
headerRow1 = 8
bookName2 = "Daily_Inventory_Master.xlsm" 'note, xlsm as the macro would need to reside somewhere, better in the book you are using every day
sheetName2 = "Daily_Inventory(m3)"
headerRow2 = 12
DestHeader = mid(bookName1,20,2) & mid(bookName1,22,2) & mid(bookName1,16,4)
'Parsing the input date, play around with the numbers or use len(bookName1)-X, Y Z to work backwards if the first part of the name changes
'Oops, forgot to open the workbooks
Workbooks.Open "C:\folderName1\" & bookName1
Workbooks.Open "C:\folderName2\" & bookName2
'1. Find the source column
iCol = 1
DoUntil Workbooks(bookName1).Sheets(sheetName1).cells(headerRow1, iCol) = "All activities")
iCol = iCol + 1
Loop
'2. Find the last row for data within that column
lastRow = Workbooks(bookName1).Sheets(sheetName1).cells(1048576,iCol).End(xlUp).Row
'3. Copy the data
Range(Workbooks(bookName1).Sheets(sheetName1).cells(headerRow1+2,iCol), _
Sheets(Workbooks(bookName1).sheetName1).cells(lastRow,iCol)).Copy
'4. Use variation of step 1 to find the destination column
iiCol = 1
DoUntil Workbooks(bookName2).Sheets(sheetname2).cells(headerRow2,iiCol) = DestHeader
iiCol = iiCol + 1
Loop
'5. Paste data in
Workbooks(bookName2).Sheets(sheetname2).cells(headerRow2+2,iiCol)._
PasteSpecial Paste:=xlPasteValues
'Close the books
Application.DisplayAlerts = False 'Disable the popups asking for confirm for saving
Workbooks(bookName1).close saveChanges:=False
Workbooks(bookName2).close saveChanges:=True
Application.DisplayAlerts = True
Further to the above, if this was going to run daily, you could automatically get todays date and use it using
currDay = Format(Date, "dd")
currMonth = Format(Date, "mm")
currYear = Format(Date, "yyyy")
so bookName1 & DestHeader would be:
bookName1 = "Daily_Inventory_" & currYear & currMonth & currDay & ".xlsx"
DestHeader = currMonth&currDay&CurrYear
I'm trying to simplify a file_split script to a point of self-service in my dept. No one really has any understanding of the language, so I was checking to see if any of this could be further simplified so coworkers don't have to update the code from the editor pane.
for instance, I have things like Basepath to designate where the files will be saved off. How can I change
Dim Basepath As String
Basepath = "C:\Users\File Cuts\"
directory as string
to something like this where a user can select a folder pathway?
Dim Basepath as filedialog
with basepath
.title = "Select save location"
.directory = .selecteditems(1)
end with
and then instances where I have specific columns to reference (target value columns for each new file, naming convention columns, etc...)
as in:
Dim Manager_Name, Login_ID, Leader
Manager_Name = SourceData(i,4)
Login_ID = SourceData(i,5)
Leader = SourceData(i,9)
to be inputted by an input box for column letter like:
Dim column_selection as variant
column_selection = InputBox("Enter Column Letter")
Manager_Name = SourceData(i,column_selection)
There are quite a few references that I'd like to see if I could change so that edits could be made without actually touching the code (the column ranges where variants like name, and login ID will be changing a lot)
rest of code:
Option Explicit
Sub File_Splits()
Dim Wb As Workbook
Dim SourceData, Mgr_Name, Login_Id
Dim i As Long, j As Long, k As Long, a As Long
Dim Destination_Cell As Range
Dim Basepath As String, strNewpath As String, strLeader As String
Basepath = "C:\File Cuts\" '1. paste in file save pathway, keep last \
Set Wb = Workbooks.Open("C:\File_Split_Mgr_Template.xlsx") '2. paste template ws address here
Set Destination_Cell = Wb.Worksheets("Manager Data").Range("A2") '3. Update worksheet name and target cell
With ThisWorkbook.Worksheets("Roster")
SourceData = .Range("I10", .Range("A" & Rows.Count).End(xlUp)) '4. change I10 to your last column letter, dont change the number(keep the 10)
End With
Wb.Activate
Call Speed_Up_Code(True)
For i = 1 To UBound(SourceData)
If SourceData(i, 5) <> Login_Id Then '5. change the 1 to login column #
If i > 9 Then
Destination_Cell.Select
strNewpath = Basepath & strLeader & "\" 'comment this out if folders aren't needed
If Len(Dir(strNewpathD, vbDirectory)) = 0 Then 'comment this out if folders aren't needed
MkDir strNewpath 'comment this out if folders aren't needed
End If 'comment this out if folders aren't needed
Wb.SaveCopyAs strNewpath & _
ValidFileName(Login_Id & "_" & Mgr_Name & "_File Name.xlsx") '6. update file name
End If
With Wb.Worksheets("Manager Data") '7. change to template sheet
.Rows(2 & ":" & .Rows.Count).ClearContents '8. change 2 to row after header(s)--if header isn't in row 1
End With
Mgr_Name = SourceData(i, 4) '9. change 1 to mgr name column
Login_Id = SourceData(i, 5) '10. change 2 to login ID column
strLeader = SourceData(i, 9) '11. change 5 to lvl 3 mgr column
j = 0
End If
a = 0
For k = 1 To UBound(SourceData, 2)
Destination_Cell.Offset(j, a) = SourceData(i, k)
a = a + 1
Next
j = j + 1
Next
If Len(Dir(strNewpath, vbDirectory)) = 0 Then
MkDir strNewpath
End If
SaveCopy Wb, strNewpath, Login_Id, Mgr_Name
Call Speed_Up_Code(False)
End Sub
Public Sub SaveCopy(Wb As Workbook, strNewpath As String, Login_Id, Mgr_Name)
Wb.SaveCopyAs strNewpath & _
ValidFileName(Login_Id & "_" & Mgr_Name & "_File Name.xlsx") '12. update file name
End Sub
Have you considered having a sheet called something like "Configuration" where users write to and your script can read from. Hidden or protected if necessary
For example, list all your configuration description in col A, and the user fills in the value next to in col B, So if A1 contains the text "Manager Name Column [A-Z] =" the user enters the value "D" or 4 in cell B1. The script become Mgr_Name = SourceData(i, wsConfig.range("B1")). I guess you could add validation to their entries.
Layout the sheet like a form in logical groups and highlight where the entry cells are. In a case like entering column names I would put them horizontal with the descripting above and entry cell below, that seems more natural. Protect all the cells except the highlighted ones.
I was tasked with creating a code that will check to see if internal hyperlinks in an excel spreadsheet worked. This code first changes the formulas that were on the spreadsheet and makes them actual hyperlinks (they were originally formulas linking the locations together). The problem that I have now is that I want to create hyperlinks ONLY if Column S has text. If it doesn't, I don't want the "E-COPY" text to be displayed. All of the text in Column S varies (not one line has the same characters), which is why I'm drawing a blank is to how I tell the program to only continue if it has any text, not anything specific. I am working with Excel 2016.
Also, I am doing this to 71935 and counting rows; is there a limit to how many it can go through? If so, what can I do about it?
Thank you!
Sub CreateHyperlinks()
Dim FN As Variant
Dim Path As Variant
Dim count As Variant
Sheets(1).Activate
count = WorksheetFunction.CountA(Sheets(1).Range("A:A"))
For i = 2 To count
If Range("AM" & i).Value = "Yes" And Columns("S") = Then
Range("E" & i).Value = ""
Path = Sheets(1).Range("R" & i).Value
FN = Sheets(1).Range("S" & i).Value
Sheets(1).Range("E" & i).Select
Selection.ClearFormats
Selection.Hyperlinks.Add Anchor:=Selection, Address:=Path & FN, TextToDisplay:="E-COPY"
Range("AM" & i).Value = " "
End If
Next i
End Sub
If you just need to check for any content in ColS then:
If Range("AM" & i).Value = "Yes" And Len(Range("S" & i).Value) > 0 Then
Few things:
'make a reference to the sheet you're working with
Dim ws As Worksheet
Dim wb As Workbook
Set wb = Excel.Application.ThisWorkbook
Set ws = wb.Worksheets(1)
'gets the absolute last row with data in it // ignores empty cells
count = ws.UsedRange.Rows.Count
personally, i hate working with named ranges, so i would suggest setting range references like so
what you wrote
Path = Sheets(1).Range("R" & i).Value
what i believe it should look like
Path = ws.Cells(i, 18).Value
if you want to test the type when working with variants, try this:
'tests the type associated with the variant. an 8 = string
If VarType(ws.Cells(i, 19).Value) = 8 Then
'do your thing
'tests if the value is null
ElseIf VarType(ws.Cells(i, 19).Value) = 0 Then
'do your other thing
here's a list of the vartype enumeration to help you out.
hope it helps!
I need an Excel macro code that opens the user specified .csv file that exists in a shared drive and combines all the text into an array variable. This code is just a part of my case function.
Eg,
My csv file looks like this(It just has one column only)
line 1:apple|orange|grapes
line 2:potato|onion
Required output
searchTerms="apple|orange|grapes|potato|onion,..."
This was my attempt in writing the code:
Case Is = 4
csvFileName = Application.GetOpenFilename(FileFilter:="CSV Files (*.csv),*.csv", Title:="Select a CSV File", MultiSelect:=False)
If csvFileName = False Then Exit Sub
lrow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
For i = 1 To lrow
counter = counter + 1
If counter = lrow Then Exit Sub
Cells(i, 1).Value
searchTerms = Trim(Cells(i, 1).Value) & "|" & " " & Cells(i + 1, 1).Value
Cells(i + 1, 1).EntireRow.Delete
i = i - 1
Next i
Using Application.Workbooks.Open (csvFileName) opened the required file as Jane suggested but still not able to figure out why its showing error at Cells(i,1).Value. So basically not able to combine all the data (in csv) into searchTerms still.
The MSDN topic for GetOpenFilename (https://msdn.microsoft.com/en-us/library/office/aa195744(v=office.11).aspx) describes what this function does:
"Displays the standard Open dialog box and gets a file name from the user without actually opening any files."
This means that after calling GetOpenFileName, your code will need to actually open the file:
csvFileName = Application.GetOpenFilename(FileFilter:="CSV Files (*.csv),*.csv", Title:="Select a CSV File", MultiSelect:=False)
If csvFileName = False Then Exit Sub
Application.Workbooks.Open (csvFileName)
UPDATE:
The line Cells(i, 1).Value is giving an error because there isn't a valid statement or instruction for VBA to handle. You can use this statement to retrieve the value from a cell:
x = Cells(i, 1).Value
or to set the value in a cell:
Cells(i, 1).Value =x
but you're not doing either of those things. This line isn't doing anything useful and can be removed.
There are several other problems with the code. The following line finds out how many rows are in the sheet, then checks the row number of that row (eg if there are 3 rows, it asks for the row number of row 3):
lrow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
You can just use:
lrow = ActiveSheet.UsedRange.Rows.Count
When you go through the loop, you take the value from the first cell, and add the pipe and the value from the current cell:
searchTerms = Trim(Cells(i, 1).Value) & "|" & " " & Cells(i + 1, 1).Value
However, this value is then thrown away when you get to the next cell, and you combine the value from the first cell with the pipe and the latest cell. This will work if there are only 2 rows, but for any more, you'll only end up with the values from the first and last cell. You could either store the updated searchTerms value in the first cell at each step in the loop, or you can just combine the values correctly as you go along.
Deleting the rows as you go along is probably causing the code to be more convoluted than it needs to be (eg needing to change the value of i within the loop and having a separate variable which exits the loop. I'd suggest avoiding that and just loop through the cells to create the searchTerms value. If you really need to delete the values, I'd do so afterwards. Here's how I've updated the code:
csvFileName = Application.GetOpenFilename(FileFilter:="CSV Files (*.csv),*.csv", Title:="Select a CSV File", MultiSelect:=False)
If csvFileName = False Then Exit Sub
Application.Workbooks.Open (csvFileName)
lrow = ActiveSheet.UsedRange.Rows.Count
For i = 1 To lrow
If i = 1 Then
searchTerms = Trim(Cells(i, 1).Value)
Else
searchTerms = searchTerms & "|" & Trim(Cells(i, 1).Value)
End If
Next i
Debug.Print searchTerms
One additional point is that you've added a space after the pipe symbol when joining the strings. I've left that in, but it's not in your sample text, so you may need to remove it.
I'm able to grab values from a closed workbook with the widely found GetValues function; it works great.
But sometimes I need to grab the formula of a cell from the closed workbook. I tried modifying GetValues to grab the cells formula but I'm getting errors.
How to get a formula (not simple value) of cells from a closed excel file?
With Sheets
For r = 2 To NewRowQty ' from second row to last row
For c = 1 To ThisColumnEnd ' out to EndColumn (from import dialogue box)
ThisCell = Cells(r, c).Address
ThisValue = GetValue(ThisPath, ThisFile, ThisSheet, ThisCell)
If ThisValue <> "0" Then
If c = 3 And r > 2 Then
Cells(r, c).Formula = GetFormula(ThisPath, ThisFile, ThisSheet, ThisCell)
Else
Cells(r, c) = ThisValue
End If
End If
Next c
Next r
End With
Calls these two functions, GetValue works fine, GetFormula won't grab the formula.
Private Function GetValue(p, f, s, c)
'p: path: The drive and path to the closed file (e.g., "d:\files")
'f: file: The workbook name (e.g., "budget.xls")
's: sheet: The worksheet name (e.g., "Sheet1")
'c: cell: The cell reference (e.g., "C4")
'Retrieves a value from a closed workbook
Dim arg As String
'Make sure the file exists
If Right(p, 1) <> "\" Then p = p & "\"
If Dir(p & f) = "" Then
GetValue = "File Not Found"
Exit Function
End If
'Create the argument
arg = "'" & p & "[" & f & "]" & s & "'!" & _
Range(c).Range("A1").Address(, , xlR1C1)
'Execute an XLM macro
GetValue = ExecuteExcel4Macro(arg)
End Function
Private Function GetFormula(p, f, s, c)
'p: path: The drive and path to the closed file (e.g., "d:\files")
'f: file: The workbook name (e.g., "budget.xls")
's: sheet: The worksheet name (e.g., "Sheet1")
'c: cell: The cell reference (e.g., "C4")
'Retrieves a value from a closed workbook
Dim arg As String
'Make sure the file exists
If Right(p, 1) <> "\" Then p = p & "\"
If Dir(p & f) = "" Then
GetFormula = "File Not Found"
Exit Function
End If
'Create the argument
arg = "'" & p & "[" & f & "]" & s & "'!" & _
Range(c).Range("A1").Address(, , xlR1C1).Formula
'Execute an XLM macro
GetFormula = ExecuteExcel4Macro(arg)
End Function
Update: Joel's first code post was the basis of what I ended up using so I marked that correct. Here's my actual implementation using a copy paste of entire row formulas. This is best because I don't know how many columns out may contains values or formulas, could be C or ZZ.
' silent opening of old file:
Application.EnableEvents = False
Set o = GetObject(FileTextBox.Text)
With Sheets
For r = 2 To NewRowQty ' from second row to last row
ThisCell = "A" & r
o.Worksheets(ThisRate).Range(ThisCell).EntireRow.Copy
Sheets(ThisRate).Range(ThisCell).PasteSpecial xlFormulas
Next r
End With
' Close external workbook, don't leave open for extended periods
Set o = Nothing
Application.EnableEvents = True
Why such convoluted code? The code you are using, for some reason, is invoking the Excel 4.0 backwards compatibility mode macro processor. I can't imagine why you would do that.
Here's a simple way to get the formula from cell Sheet1!A1 of c:\tmp\book.xlsx:
Dim o As Excel.Workbook
Set o = GetObject("c:\tmp\Book.xlsx")
MsgBox o.Worksheets("Sheet1").Cells(1, 1).Formula
Set o = Nothing ' this ensures that the workbook is closed immediately
If you insist on running Excel 4 - style macros (obsolete in 1994!) you need to use the XLM function GET.FORMULA to retrieve the formula instead of the value as follows:
arg = "GET.FORMULA('" & p & "[" & f & "]" & s & "'!" & _
Range(c).Range("A1").Address(, , xlR1C1) & ")"
Note that the result will have formulas using R1C1 notation instead of A1 notation.
Converting back to A1 notation (if you really want to do that) is left as an exercise to the reader.