I am currently using the set value method to copy data from multiple workbooks. I can currently loop through all workbooks and set the values from one sheet, worksheet2(Title) as seen below, and copy them to "thisWorkbook" on "sheet1", my destination. How can I loop through worksheets 3 to 9 and copy the range A2:C57 into columns G,H,I using the same set value method?
Sub GetData()
Dim MyPath As String
Dim FileName As String
Dim SheetName As String
Dim NewRow As Long
MyPath = "C:\attach"
SheetName = "Title"
FileName = Dir(MyPath & "\*.xlsx")
Do While FileName <> ""
If FileName <> ThisWorkbook.Name Then
With ThisWorkbook.Sheets("Sheet1")
NewRow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
With .Range("A" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B4"
.Value = .Value
End With
With .Range("B" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B5"
.Value = .Value
End With
With .Range("C" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B6"
.Value = .Value
End With
With .Range("D" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!B7"
.Value = .Value
End With
With .Range("E" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!A1"
.Value = .Value
End With
With .Range("F" & NewRow)
.Formula = "='" & MyPath & "\[" & FileName & "]" & SheetName & "'!A2"
.Value = .Value
End With
'Copy the range A2:C57 from workheets (3 to 9) and past into columns G,H,I in thisworkbook from every workbook in folder.
'For sheets 3 to 9 set the value range A2:C57 to G,H,I in thisworkbook. This would be done for every workbook in the folder
End With
End If
FileName = Dir
Loop
ThisWorkbook.Sheets("Sheet1").Columns.AutoFit
End Sub
I'm not entirely sure if this is what you're asking, but I think the range.copy is what you want.
To get the entire worksheet 3-9 you can use
' A2:C57 = Cells (2,1),Cells(57,3)
For Sheetindex= 3 to ThisWorkbook.Worksheets.Count
'Copy Worksheet 3 A2:C57
Set SourceRange = ThisWorkbook.WorkSheets(Sheetindex).Range(Cells(2,1),Cells(57,3))
' Paste it in Columns G,H,I starting in Row 1.
SourceRange.Copy (ThisWorkbook.Worksheets("Sheet1").Cells("G1"))
Next Sheetindex
Related
I have a set of data that is downloaded from SQL Server. Data can be huge. I need to rearrange it to a specific column order template before exporting it to either CSV or XLSX, really does not matter.
In this instance, I have put together a code that takes the original data (From Col A to Co; Q and set them up in the same sheet from Col T to Col AB) then attempt to export that range (T:AB to Last row) as CSV.
First part of the code works, pretty straightforward. However, I am struggling to export the range to either CSV or XLSX. Currently it is exporting data into another file only in row 1.
CODE
Sub test()
Dim LR As Long
Dim myCSVFileName As String
Dim myWB As Workbook
Dim rngToSave As range
Dim fNum As Integer
Dim csvVal As String
LR = Sheets("AAP").Cells(Rows.count, "A").End(xlUp).row
Sheets("AAP").range("T2:T" & LR).Value = Sheets("AAP").range("B2:B" & LR).Value
Sheets("AAP").range("U2:U" & LR).Value = Sheets("AAP").range("C2:C" & LR).Value
Sheets("AAP").range("V2:V" & LR).Value = Sheets("AAP").range("I2:I" & LR).Value
Sheets("AAP").range("W2:W" & LR).Value = Sheets("AAP").range("J2:J" & LR).Value
Sheets("AAP").range("X2:X" & LR).Value = Sheets("AAP").range("E2:E" & LR).Value
Sheets("AAP").range("Y2:Y" & LR).Value = Sheets("AAP").range("F2:F" & LR).Value
Sheets("AAP").range("Z2:Z" & LR).Value = Sheets("AAP").range("H2:H" & LR).Value
Sheets("AAP").range("AA2:AA" & LR).Value = Sheets("AAP").range("G2:G" & LR).Value
Sheets("AAP").range("AB2:AB" & LR).Value = "AA_FEES"
Set myWB = ThisWorkbook
myCSVFileName = myWB.Path & "\" & "CSV-Exported-File-" & VBA.Format(VBA.Now, "dd-MMM-yyyy hh-mm") & ".csv"
csvVal = ""
fNum = FreeFile
Set rngToSave = range("T2:AB" & LR)
Open myCSVFileName For Output As #fNum
For i = 1 To rngToSave.Rows.count
For j = 1 To rngToSave.Columns.count
csvVal = csvVal & Chr(34) & rngToSave(i, j).Value & Chr(34) & ","
Next
Print #fNum, Left(csvVal, Len(csvVal) - 2)
csvVal = ""
Next
Close #fileNumber
End Sub
Any advise how to make this more efficient would be greatly appreciated.
The easiest method to export that to a CSV would be to copy the worksheet to no destination. This creates a new workbook that is the new ActiveWorkbook with a single worksheet that is a copy of the original. After deleting columns A:S, SaveAs xlCSV.
...
workSheets("AAP").copy
with activeworkbook
application.displayalerts = false
.worksheets(1).range("A:S").entirecolumn.delete
.saveas filename:=myCSVFileName, fileformat:=xlcsv
.close savechanges:=false
application.displayalerts = true
end with
Hello I have a little question for adding data to an existing chart.
Now I have a worksheet containing a data series with months for the years in the 2nd row of the sheet. So the months are for example B2 1.2017, C2 2.2017, and in the rows 3,4,5,6,7 and 8 there is always data for that month.
Now I just want my macro to add the new Month plus the data of the rows below to my existing chart.
the code I have so far is this:
Worksheets("Summary").ChartObjects("Chart").Activate
ActiveChart.SeriesCollection.Add _
Source:=Worksheets("Summary").Range("B2:B8")
now this does just create new data series but there is actually no new data added to the chart.
The code below might seem a little long, but it's the safest way to add a new Series with Data to an existing Chart.
I'm setting all the necessary Objects so the code will be as "safe-proof" as can be.
Code
Option Explicit
Sub AddSeriestoChart()
Dim ws As Worksheet
Dim ChtRng As Range
Dim ChtObj As ChartObject
Dim Ser As Series
' set the Worksheet object
Set ws = ThisWorkbook.Worksheets("Summary")
' Set the Chart Object
Set ChtObj = ws.ChartObjects("Chart")
' Set the Range of the Chart's source data
Set ChtRng = ws.Range("B2:B8")
With ChtObj
' add a new series to chart
Set Ser = .Chart.SeriesCollection.NewSeries
' set the source data of the new series
Ser.Values = "=" & ChtRng.Address(False, False, xlA1, xlExternal)
End With
End Sub
Edit 1: to modify existing Series data, use something like the code below :
With ChtObj
For i = 1 To .Chart.SeriesCollection.Count
Set Ser = .Chart.SeriesCollection(i)
' set the source data of the new series
Set ChtRng = ws.Range("B" & i + 2)
Ser.Values = "=" & ChtRng.Address(False, False, xlA1, xlExternal)
Set ChtRng = Nothing
Next i
End With
This is what I would use
wsMetric.ChartObjects("Chart").Chart
'This one will link data from another workbook
.SeriesCollection(1).Values = "='[" & wb.Name & "]" & ws.Name & "'!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow2
'Debug.Print "='[" & wb.Name & "]" & ws.Name & "'!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow2 'Returns ='[Book1.xlsm]Sheet1'!$A$1:$A$11
'This one will link data from the same workbook, same or different sheet
.SeriesCollection(1).Values = "=" & ws.Name & "!$" & sCol & "$" & lRow & ":$" & sCol2 & "$" & lRow 2
'Debug.print "=" & ActiveSheet.Name & "!$" & scol & "$" & lrow & ":$" & scol2 & "$" & lrow2 'Returns =Sheet1!$A$1:$A$11
End With
This doesn't use .Activate and directly accesses the chart
I have a weird problem with my code VBA.
I am using excel 2010, i wrote a code which works perfectly on multiple source except some.
my code object is to copy the same cell from the same sheet from multiple workbooks and paste it into a destination workbook as a column.
My code runs on 50 workbooks without any problem, except 2.
Notice that those 2 are the same sample as the others, but of course different values.
If I ad those 2 workbooks with the other 50, I have an error message 'Error of execution'1004' and I should then stop the process.
the yellow line stand on a the formula :
myFile = Dir(myPath & myExtension)
Set y = Workbooks.Open(destFullpath)
`With y.Sheets("Feuil1").Range("A" & i + 1)
**.Formula = "='" & "[" & myFile & "]Para RF'!L2" 'date**
.Value = .Value
y.Sheets("Feuil1").Range("A" & i + 1).NumberFormat = "dd/mm/yy;#" ' <-- to specify that it is a date format
End With`
Do you have an idea why can this problem occur?
what should i do? Is there anything to change with the settings etc?
Note That I have tried to save those 2 as excel without macros, so xlsx and did not run.
I tried to unprotect the sheets: did not run
I broke the link between them and other one: this didn't help either!!!
what can it be??
Thank you!!
This is the entire code :
Sub LoopAllExcelFilesInFolderr()
'PURPOSE: To loop through all Excel files in a user specified folder and
perform a set task on them
Dim wb As Workbook
Dim myPath As String
Dim myFile As String
Dim destFullpath As String
Dim myExtension As String
DimFldrPicker As FileDialog
Dim y As Workbook
Dim i As Integer
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
'Application.DisplayAlerts = False
'Retrieve Target Folder Path From User
myPath = "Z:\VBA\para_macro\"
destFullpath = "Z:\VBA\base-macro.xlsx"
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "*.xls*"
'Target Path with Ending Extention
myFile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
Set y = Workbooks.Open(destFullpath)
For i = 1 To y.Sheets("Feuil1").Range("M1")
'Ensure Workbook has opened before moving on to next line of code
DoEvents
With y.Sheets("Feuil1").Range("A" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!L2" 'date devis
.Value = .Value
y.Sheets("Feuil1").Range("A" & i + 1).NumberFormat = "dd/mm/yy;#" ' <-- to specify that it is a date format
End With
With y.Sheets("Feuil1").Range("B" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!E11" 'date d'installation
.Value = .Value
End With
With y.Sheets("Feuil1").Range("c" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!H5" 'type
.Value = .Value
End With
With y.Sheets("Feuil1").Range("D" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!H8" 'montant final
.Value = .Value
.NumberFormat = "0.000"
End With
With y.Sheets("Feuil1").Range("E" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!K8" 'montant tarif
.Value = .Value
.NumberFormat = "0.000"
End With
With y.Sheets("Feuil1").Range("F" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!K10" 'remise
.Value = .Value
.NumberFormat = "0.000"
End With
With y.Sheets("Feuil1")
.Range("G2:G" & .Cells(.Rows.count, "F").End(xlUp).Row).Formula = "=$F2/$E2"
y.Sheets("Feuil1").Range("G2:G" & .Cells(.Rows.count, "F").End(xlUp).Row).NumberFormat = "0.00%"
End With
With y.Sheets("Feuil1").Range("H" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!D6" 'société
.Value = .Value
End With
With y.Sheets("Feuil1").Range("I" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!F8" 'ville
.Value = .Value
End With
With y.Sheets("Feuil1").Range("J" & i + 1)
.Formula = "='" & "[" & myFile & "]Para RF'!G5" 'nom vendeur
.Value = .Value
End With
'Ensure Workbook has closed before moving on to next line of code
DoEvents
'Get next file name
myFile = Dir()
Next
'Save and Close Workbook
y.Close saveChanges:=True
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
You're not iterating 50 workbooks. You're iterating 50 file names.
.Formula = "='" & "[" & myFile & "]Para RF'!L2"
Error 1004 on this line means myFile somehow contains invalid characters, or (more likely) that there is no worksheet named Para RF in that workbook.
Try typing ='[that file name.xlsx]Para RF'!L2 directly in a cell (in any workbook). You'll see this:
So, Verify that your formula contains a valid path, workbook, range name, and cell reference.
If there is such a Para RF sheet in the failing workbook, make sure there's no leading/trailing spaces.
I adjusted the code I found on the Internet to pull data from the files in the folder and put them in one master sheet.
However, the numer of files will grow very quickly every week, so for that reason I would like to implement in the code that macro will skip the files that were already processed. I would like to do it by the looking up the file name in the master sheet (column U).
Please find the code below:
Option Explicit
Const FOLDER_PATH = "Z:\...\...\...\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim fName As String
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
Dim wsMaster As Worksheet
Dim NR As Long
rowTarget = 3
'Setup
Application.ScreenUpdating = False 'speed up macro execution
Application.EnableEvents = False 'turn off other macros for now
Application.DisplayAlerts = False 'turn off system messages for now
Set wsMaster = ThisWorkbook.Sheets("Arkusz1") 'sheet report is built into
With wsMaster
If MsgBox("Clear the old data first?", vbYesNo) = vbYes Then
.UsedRange.Offset(2).Columns(3).Clear
.UsedRange.Offset(2).Columns(4).Clear
.UsedRange.Offset(2).Columns(5).Clear
.UsedRange.Offset(2).Columns(6).Clear
.UsedRange.Offset(2).Columns(7).Clear
.UsedRange.Offset(2).Columns(8).Clear
.UsedRange.Offset(2).Columns(9).Clear
.UsedRange.Offset(2).Columns(10).Clear
.UsedRange.Offset(2).Columns(11).Clear
.UsedRange.Offset(2).Columns(12).Clear
.UsedRange.Offset(2).Columns(13).Clear
.UsedRange.Offset(2).Columns(14).Clear
.UsedRange.Offset(2).Columns(15).Clear
.UsedRange.Offset(2).Columns(17).Clear
.UsedRange.Offset(2).Columns(18).Clear
.UsedRange.Offset(2).Columns(20).Clear
NR = 3
Else
NR = .Range("A" & .Rows.Count).End(xlUp).Row + 1 'appends data to existing data
End If
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error GoTo errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Arkusz1")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbSource.Worksheets(3) 'EDIT IF NECESSARY
'import the data
With wsTarget
.Range("C" & rowTarget).Value = wsSource.Range("F4").Value
.Range("D" & rowTarget).Value = wsSource.Range("J4").Value
.Range("E" & rowTarget).Value = wsSource.Range("J7").Value
.Range("F" & rowTarget).Value = wsSource.Range("J10").Value
.Range("G" & rowTarget).Value = wsSource.Range("J19").Value
.Range("H" & rowTarget).Value = wsSource.Range("L19").Value
.Range("I" & rowTarget).Value = wsSource.Range("H17").Value
.Range("J" & rowTarget).Value = wsSource.Range("N27").Value
.Range("K" & rowTarget).Value = wsSource.Range("N29").Value
.Range("L" & rowTarget).Value = wsSource.Range("N36").Value
.Range("M" & rowTarget).Value = wsSource.Range("N38").Value
.Range("N" & rowTarget).Value = wsSource.Range("J50").Value
.Range("O" & rowTarget).Value = wsSource.Range("L50").Value
.Range("Q" & rowTarget).Value = wsSource.Range("J52").Value
.Range("R" & rowTarget).Value = wsSource.Range("L52").Value
.Range("T" & rowTarget).Value = wsSource.Range("N57").Value
'optional source filename in the last column
.Range("U" & rowTarget).Value = sFile
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
End If
'Format columns to the desired format
.UsedRange.Offset(2).Columns(7).NumberFormat = "### ### ##0"
.UsedRange.Offset(2).Columns(8).NumberFormat = "### ### ##0"
.UsedRange.Offset(2).Columns(9).NumberFormat = "#,##0.00 $"
.UsedRange.Offset(2).Columns(10).NumberFormat = "#,##0.00 $"
.UsedRange.Offset(2).Columns(11).NumberFormat = "#,##0.00 $"
.UsedRange.Offset(2).Columns(12).NumberFormat = "#,##0.00 $"
.UsedRange.Offset(2).Columns(13).NumberFormat = "#,##0.00 $"
.UsedRange.Offset(2).Columns(14).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(15).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(16).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(17).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(18).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(19).NumberFormat = "0.00%"
.UsedRange.Offset(2).Columns(20).NumberFormat = "0.00%"
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End With
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
I tried to make it by If and GoTo statement but I have very little knowledge in VBA and I have no idea how to actually formulate it skip files which names are already in master sheet.
Thanks in advance!
I'll assume for the moment that the file name in column U is the entire path with file extension. i.e. C:\Users\SL\Desktop\TestFile.xls
You can use the Find method to look for any entries in column U that match sFile at the start of each loop. If a match is found, skip over the file and move on, otherwise process it. Make sure you place sFile = Dir() outside the If statement to avoid an infinite loop.
Dim PathMatch As Range
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
With wsMaster.Range("U:U")
Set PathMatch = .Find(What:=sFile, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If Not PathMatch Is Nothing Then
Debug.Print "File already processed, skip to next file."
Else
Debug.Print "File not processed yet, do it now"
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = wbSource.Worksheets(3) 'EDIT IF NECESSARY
'import the data
With wsTarget
.Range("C" & rowTarget).Value = wsSource.Range("F4").Value
.Range("D" & rowTarget).Value = wsSource.Range("J4").Value
.Range("E" & rowTarget).Value = wsSource.Range("J7").Value
.Range("F" & rowTarget).Value = wsSource.Range("J10").Value
.Range("G" & rowTarget).Value = wsSource.Range("J19").Value
.Range("H" & rowTarget).Value = wsSource.Range("L19").Value
.Range("I" & rowTarget).Value = wsSource.Range("H17").Value
.Range("J" & rowTarget).Value = wsSource.Range("N27").Value
.Range("K" & rowTarget).Value = wsSource.Range("N29").Value
.Range("L" & rowTarget).Value = wsSource.Range("N36").Value
.Range("M" & rowTarget).Value = wsSource.Range("N38").Value
.Range("N" & rowTarget).Value = wsSource.Range("J50").Value
.Range("O" & rowTarget).Value = wsSource.Range("L50").Value
.Range("Q" & rowTarget).Value = wsSource.Range("J52").Value
.Range("R" & rowTarget).Value = wsSource.Range("L52").Value
.Range("T" & rowTarget).Value = wsSource.Range("N57").Value
'optional source filename in the last column
.Range("U" & rowTarget).Value = sFile
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
End If
sFile = Dir()
Loop
If you only have the file name and not the path you'll need to parse sFile accordingly. Here are a few ways to do that.
I'm getting an "application-defined or object-defined error" being thrown when I try to set a cell in my active sheet to a formula. I think its due to me trying to use the Sheets.Name function in the formula, see code below:
Public Sub getChannels()
Dim lastRow As Long
Dim i As Integer, counter As Integer
Dim rng As Range, rngB As Range, rngC As Range
Dim sht As Worksheet
Dim test As String
Set sht = Sheets("Summary Sheet - 30-07-2015")
sht.Activate
lastRow = sht.Cells(sht.Rows.Count, "B").End(xlUp).Row
For counter = 1 To lastRow Step 3
If ActiveSheet.Cells(counter, 12) = "LTE 2C" Then
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH(""'"" & sht.name &""'""!RC[-14],'LTE 2C'!C[-11],0))"
ActiveSheet.Cells(counter, 17) = _
"=INDEX('LTE 2C'!C[53],MATCH(""'"" & sht.name &""'""!RC[-15],'LTE 2C'!C[-12],0))"
ActiveSheet.Cells(counter, 18) = _
"=INDEX('LTE 2C'!C[55],MATCH(""'"" & sht.name &""'""!RC[-16],'LTE 2C'!C[-13],0))"
Range("P" & counter & ":R" & counter).Select
Selection.Copy
Range("P" & counter + 1 & ":P" & counter + 2).Select
ActiveSheet.Paste
End If
Next
End Sub
Am I missing something obvious?
Change your formula like this:
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH(" & "'" & sht.name & "'" & "!RC[-14],'LTE 2C'!C[-11],0))"
ActiveSheet.Cells(counter, 17) = _
"=INDEX('LTE 2C'!C[53],MATCH(" & "'" & sht.name & "'" & "!RC[-15],'LTE 2C'!C[-12],0))"
ActiveSheet.Cells(counter, 18) = _
"=INDEX('LTE 2C'!C[55],MATCH(" & "'" & sht.name & "'" & "!RC[-16],'LTE 2C'!C[-13],0))"
Nelly is correct, but another way to do this would be to simply remove the unnecessary extra string for each apostrophe and replace it with this:
ActiveSheet.Cells(counter, 16) = _
"=INDEX('LTE 2C'!C[55],MATCH('" & sht.name & "'!RC[-14],'LTE 2C'!C[-11],0))"
Where the apostrophes are just attached to the strings before and after. It really makes no difference, but it removes the extra (&)s.