I have a master Excel workbook and I want to create a macro to import data from a specified range from 7 Excel files. These files are all the same in structure except for the actual data. With the import macro/button I basically want to get an open files dialogue, select all the files and let the macro add the data in the range to the master one by one. I have taken some Inspiration from another post here, which makes it work for one single file: The to be adjusted code would have to be able to select the 7 files and dynamically add it to the target range one by one.
Sub getData()
Dim slaveBook As Workbook
Dim filter As String
Dim caption As String
Dim slaveFilename As String
Dim slaveWorkbook As Workbook
Dim targetWorkbook As Workbook
Set targetWorkbook = Application.ActiveWorkbook
filter = "Team file (*.xlsm),*.xlsm"
caption = "Please select the team file"
slaveFilename = Application.GetOpenFilename(filter, , caption)
Set slaveWorkbook = Application.Workbooks.Open(slaveFilename)
Dim targetSheet As Worksheet
Set targetSheet = targetWorkbook.Worksheets("MASTER")
Dim sourceSheet As Worksheet
Set sourceSheet = slaveWorkbook.Worksheets("Interface")
targetSheet.Range("B5", "J8").Value = sourceSheet.Range("B5", "J8").Value
slaveWorkbook.Close
End Sub
Sub getData()
Dim slaveBook As Workbook
Dim filter As String
Dim caption As String
Dim slaveFilename As String
Dim slaveWorkbook As Workbook
Dim targetWorkbook As Workbook
i = 1
For i = 1 To 7
Set targetWorkbook = Application.ActiveWorkbook
On Error GoTo errorhandler
filter = "Team file (*.xlsm),*.xlsm"
caption = "Please select the team file"
slaveFilename = Application.GetOpenFilename(filter, , caption)
Set slaveWorkbook = Application.Workbooks.Open(slaveFilename)
On Error GoTo 0
On Error GoTo err2
Dim targetSheet As Worksheet
Set targetSheet = targetWorkbook.Worksheets("MASTER")
Dim sourceSheet As Worksheet
Set sourceSheet = slaveWorkbook.Worksheets("Interface")
If i = 1 Then targetSheet.Range("B5", "J8").Value = sourceSheet.Range("B5", "J8").Value
If i = 2 Then targetSheet.Range("B9", "J12").Value = sourceSheet.Range("B5", "J8").Value
If i = 3 Then targetSheet.Range("B13", "J16").Value = sourceSheet.Range("B5", "J8").Value
If i = 4 Then targetSheet.Range("B17", "J20").Value = sourceSheet.Range("B5", "J8").Value
If i = 5 Then targetSheet.Range("B21", "J24").Value = sourceSheet.Range("B5", "J8").Value
If i = 6 Then targetSheet.Range("B25", "J28").Value = sourceSheet.Range("B5", "J8").Value
If i = 7 Then targetSheet.Range("B29", "J32").Value = sourceSheet.Range("B5", "J8").Value
slaveWorkbook.Close False 'wont prompt to save changes (will close without saving),
'remove false if you do need to save changes
i = i + 1
Next i
Exit Sub
errorhandler:
MsgBox "You didn't select a valid file!"
Exit Sub
err2:
MsgBox "Error - Most likely reason is that the required sheet is not found in Slave workbook"
Exit Sub
End Sub
Updated - Have changed the code so now it should save all the information to your "MASTER" sheet underneath eachother. Obviously this is a very simple way of doing it, and restricts you to only opening 7 files before the code ends. If you wanted to add more in the future you could simply extend the array and range code or modify the range code to look for the last available row to paste data on (LastRow = Range("J65536").End(xlUp).Row) is a good place to start
Related
For a vlookup formula, I am using an inputbox option to select a couple of workbooks (OpenBook_PY and CY) for source data and creating a new workbook (Comp_Book) for main data.
The inputbox function is working successfully however I am facing problem when defining the worksheets in each of the above mentioned book.
Error is type 13 : mismatch error
The problem starts at the 3rd last line, when setting M_Sheet
Dim CY_TB As Variant
Dim OpenBook_CY As Workbook
Dim PY_TB As Variant
Dim OpenBook_PY As Workbook
Dim Comp_Book As Workbook
Set Comp_Book = Workbooks.Add
Application.ScreenUpdating = False
CY_TB = Application.GetOpenFilename(Title:="Open Current Period TBC", FileFilter:="Excel Files (*.xls*),*xls*")
Set OpenBook_CY = Application.Workbooks.Open(CY_TB)
If CY_TB <> False Then
OpenBook_CY.Activate
Worksheets(1).Select
range(range("B6"), range("B" & Rows.Count).End(xlUp)).Copy Comp_Book.Sheets(1).range("B6")
Dim CY_Rnge As range
End If
'TBC of PY
PY_TB = Application.GetOpenFilename(Title:="Open Prior Period TBC", FileFilter:="Excel Files (*.xls*),*xls*")
Set OpenBook_PY = Application.Workbooks.Open(PY_TB)
If PY_TB <> False Then
OpenBook_PY.Activate
Worksheets(1).Select
End If
Dim M_Sheet As Worksheet, CY_Sheet As Worksheet, PY_Sheet As Worksheet, N_Sheet As Worksheet
Dim M_LR As Long, CY_LR As Long, PY_LR As Long, r As Long
Dim CY_Rng As range, PY_Rng As range
Set M_Sheet = Workbooks(Comp_Book).Worksheets("Sheet1")
Set CY_Sheet = Workbooks(OpenBook_CY).Worksheets("Trial-New")
Set PY_Sheet = Workbooks(OpenBook_PY).Worksheets("Trial-New")
The problem is the Workbooks call:
Set M_Sheet = Workbooks(Comp_Book).Worksheets("Sheet1")
Comp_Book is a Workbook, so all you need is:
Set M_Sheet = Comp_Book.Worksheets("Sheet1")
... and similarly for the next two lines.
I have created a macro to import data from another workbook, but i have to set which row to start. I was wondering how i would alter the code to paste the import data to the last empty row (so its adding to the table).
Currently the macro, prompts to click the file you would like to import, then imports the data from certain col from source WB to target WB. But as you can see it as been assigned the row to paste. My question is how do i get it to paste at the last empty row, so it is collecting the data rather then over writing the data.
Would i need to change the "targetSheet.Range("R2", "R4000").Value = sourceSheet.Range("Q2", "Q4000").Value"
Public Sub Extract_Excel_file()
''//--------------------------------------------
' Get customer workbook...
Dim customerBook As Workbook
Dim filter As String
Dim caption As String
Dim customerFilename As String
Dim customerWorkbook As Workbook
Dim targetWorkbook As Workbook
' make weak assumption that active workbook is the target
Set targetWorkbook = Application.ActiveWorkbook
' get the customer workbook
filter = "Text files (*.xlsx),*.xlsx"
caption = "Please Select an input file "
customerFilename = Application.GetOpenFilename(filter, , caption)
Set customerWorkbook = Application.Workbooks.Open(customerFilename)
' assume range is A1 - C10 in sheet1
' copy data from customer to target workbook
Dim targetSheet As Worksheet
Set targetSheet = ThisWorkbook.Sheets("Raw Data")
Dim sourceSheet As Worksheet
Set sourceSheet = customerWorkbook.Worksheets(1)
sourceSheet.Range("A2", "V400").NumberFormat = "#" ''//Set all cells to
text format.
' sourceSheet.Range("A2", "A4000").NumberFormat = "#" ''//Set all cells
to text format.
targetSheet.Range("B2", "B4000").Value = sourceSheet.Range("A2",
"A4000").Value
targetSheet.Range("C2", "C4000").Value = sourceSheet.Range("B2",
"B4000").Value
targetSheet.Range("D2", "D4000").Value = sourceSheet.Range("C2",
"C4000").Value
targetSheet.Range("E2", "E4000").Value = sourceSheet.Range("D2",
"D4000").Value
targetSheet.Range("F2", "F4000").Value = sourceSheet.Range("E2",
"E4000").Value
targetSheet.Range("G2", "G4000").Value = sourceSheet.Range("F2",
"F4000").Value
targetSheet.Range("H2", "H4000").Value = sourceSheet.Range("G2",
"G4000").Value
targetSheet.Range("I2", "I4000").Value = sourceSheet.Range("H2",
"H4000").Value
targetSheet.Range("J2", "J4000").Value = sourceSheet.Range("I2",
"I4000").Value
targetSheet.Range("K2", "K4000").Value = sourceSheet.Range("J2",
"J4000").Value
targetSheet.Range("L2", "L4000").Value = sourceSheet.Range("K2",
"K4000").Value
targetSheet.Range("M2", "M4000").Value = sourceSheet.Range("L2",
"L4000").Value
targetSheet.Range("N2", "N4000").Value = sourceSheet.Range("M2",
"M4000").Value
targetSheet.Range("O2", "O4000").Value = sourceSheet.Range("N2",
"N4000").Value
targetSheet.Range("P2", "P4000").Value = sourceSheet.Range("O2",
"O4000").Value
targetSheet.Range("L2", "L4000").Value = sourceSheet.Range("P2",
"P4000").Value
targetSheet.Range("Q2", "Q4000").Value = sourceSheet.Range("L2",
"L4000").Value
targetSheet.Range("R2", "R4000").Value = sourceSheet.Range("Q2",
"Q4000").Value
' Close customer workbook
Application.DisplayAlerts = False ''//Don't promt to Save
customerWorkbook.Close
Application.DisplayAlerts = True '' undo Don't promt to Save
End Sub
I just want it to collect the data rather then overriding it each month.
I am trying to make program to see the excel workbook that is already open, but it doesn't. Controlling with xlApp.Visible = True line creates a new excel document instead making the open one visible. Any suggestions please?
Edit: I added the rest of the code here. Using catia, I am trying to reach the open excel worksheet and make modifications on it. In this case I am trying to select A1:E5 cells one by one and clear their contents
Sub CATMain()
Dim xlApp As Excel.Application
'On Error Resume Next
Set xlApp = VBA.GetObject("", "Excel.Application")
Dim exlBook As Workbook
Set exlBook = xlApp.ActiveWorkbook
Dim exlSheet As Worksheet
Set exlSheet = xlApp.ActiveSheet
xlApp.Visible = True
Dim cell1 As Integer
Dim cell2 As Integer
Dim cell3 As Integer
Dim cell4 As Integer
Dim myRange As Range
cell1 = 1 'InputBox("Tablo Başlangıç Satırını Girin: ")
cell2 = 1 'InputBox("Tablo Başlangıç Sütununu Girin: ")
cell3 = 5 'InputBox("Tablo Bitiş Satırını Girin: ")
cell4 = 5 'InputBox("Tablo Bitiş Sütununu Girin: ")
Set myRange = exlSheet.Range(Cells(cell1, cell2), Cells(cell3, cell4))
myRange.ClearContents
End Sub
I'm in the middle of writing a script that populates an excel spreadsheet with data from an MS Project file. I would like the script to recognize the title name of the MS Project columns as I have a number of custom columns with different names (custom number fields are populated with different names)
The code below was my attempt, but i'm getting an error when it comes to writing the value of the task column title to the sheet, am I doing something wrong here?
Sub PopulateSheet()
Dim Proj As MSProject.Application
Dim NewProj As MSProject.Project
Dim t As MSProject.Task
Dim xl as workbook
Dim s as worksheet
Dim Newsheet as worksheet
Set Xl = ThisWorkbook
BookNam = Xl.Name
Set Newsheet = Xl.Worksheets.Add
'Code to find and open project files
Set Proj = New MSProject.Application
MsgBox ("Please Select MS Project File for Quality Checking")
'Select Project File
FileOpenType = Application.GetOpenFilename( _
FileFilter:="MS Project Files (*.mpp), *.mpp", _
Title:="Select MS Project file", _
MultiSelect:=False)
'Detect if File is selected, if not then stop code
If FileOpenType = False Then
MsgBox ("You Havent Selected a File")
Exit Sub
End If
'Write the FileOpenType variant to two separate strings
NewProjFilePath = Left$(FileOpenType, InStrRev(FileOpenType, "\"))
NewProjFileName = Mid$(FileOpenType, InStrRev(FileOpenType, "\") + 1)
Newsheet.Name = NewProjFileName
Set s = Newsheet
'Populate spreadsheet header row with column titles from MS Project
s.Range("A1").Value = t.Number1 ***<-- Error '91' - Object variable or With block variable not set***
End Sub
Here is generic code that loops through the fields in the active task table and prints out the field headings as displayed in the table.
Sub GetTaskTableHeaders()
Dim t As Table
Set t = ActiveProject.TaskTables(ActiveProject.CurrentTable)
Dim f As TableField
For Each f In t.TableFields
If f.Field > 0 Then
Dim header As String
Dim custom As String
custom = Application.CustomFieldGetName(f.Field)
If Len(f.Title) > 0 Then
header = f.Title
ElseIf Len(custom) > 0 Then
header = custom
Else
header = Application.FieldConstantToFieldName(f.Field)
End If
Debug.Print "Field " & f.Index, header
End If
Next f
End Sub
Note that fields can be customized at the project level to be given a different title, or they can be customized at the table level. This code looks for both customizations and if neither is found, the field name is used.
Try the code below, explanation inside the code's comments:
Option Explicit
Sub PopulateSheet()
Dim Proj As MSProject.Application
Dim NewProj As MSProject.Project
Dim PjTableField As MSProject.TableField ' New Object
Dim PjTaskTable As MSProject.Table ' New Object
Dim t As MSProject.task
Dim xl As Workbook
Dim s As Worksheet
Dim Newsheet As Worksheet
Dim BookName As String
Dim FileOpenType
Dim NewProjFilePath As String, NewProjFileName As String
Set xl = ThisWorkbook
BookName = xl.Name
Set Newsheet = xl.Worksheets.Add
'Code to find and open project files
Set Proj = New MSProject.Application
MsgBox ("Please Select MS Project File for Quality Checking")
'Select Project File
FileOpenType = Application.GetOpenFilename( _
FileFilter:="MS Project Files (*.mpp), *.mpp", _
Title:="Select MS Project file", _
MultiSelect:=False)
'Detect if File is selected, if not then stop code
If FileOpenType = False Then
MsgBox ("You Havent Selected a File")
Exit Sub
End If
'Write the FileOpenType variant to two separate strings
NewProjFilePath = Left$(FileOpenType, InStrRev(FileOpenType, "\"))
NewProjFileName = Mid$(FileOpenType, InStrRev(FileOpenType, "\") + 1)
Newsheet.Name = NewProjFileName
Set s = Newsheet
' Open MS-Project File
Proj.FileOpen NewProjFilePath & NewProjFileName
Set NewProj = Proj.ActiveProject
' ===== New code Section =====
' set the Table object
Set PjTaskTable = NewProj.TaskTables(NewProj.CurrentTable)
' loop through all tablefields in table
For Each PjTableField In PjTaskTable.TableFields
If PjTableField.Field = pjTaskNumber1 Then ' check if currect field numeric value equals the numeric value of "Number1"
'Populate spreadsheet header row with column titles from MS Project
s.Range("A1").Value = PjTableField.Title ' populate "A1" with the field's title and
End If
Next PjTableField
End Sub
I am trying to read a specific set of columns from a workbook (every week it is a new workbook) and copy them into another workbook. This I have been able to do, but I think there is a cleaner way to do it!! My code is very bulky and problematic, as every week I need to read info from a different workbook so I have to go back into the code and change the workbook file name. I would love any input on how to improve the code and speed up changing the file name for the workbook from which columns are copied....for example is it possible to ask the user to input the file name in place of a static name??
Any feedback / suggestions are greatly appreciated!!! My code is below:
Sub CopyColumnToWorkbook()
Dim sourceColumns As Range, targetColumns As Range
Dim qw As Range, rw As Range
Dim sd As Range, fd As Range
Dim bu As Range, hu As Range
Dim zx As Range, gx As Range
Dim op As Range, wp As Range
Dim ty As Range, ly As Range
Set sourceColumns = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("L")
Set targetColumns = Workbooks("LU.xls").Worksheets(1).Columns("A")
Set qw = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("G")
Set rw = Workbooks("LU.xls").Worksheets(1).Columns("B")
Set sd = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("C")
Set fd = Workbooks("LU.xls").Worksheets(1).Columns("C")
Set bu = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("N")
Set hu = Workbooks("LU.xls").Worksheets(1).Columns("D")
Set zx = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("R")
Set gx = Workbooks("LU.xls").Worksheets(1).Columns("E")
Set op = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("S")
Set wp = Workbooks("LU.xls").Worksheets(1).Columns("F")
Set ty = Workbooks("WERT_2013_01_24.xlsx").Worksheets(1).Columns("I")
Set ly = Workbooks("LU.xls").Worksheets(1).Columns("G")
sourceColumns.Copy Destination:=targetColumns
qw.Copy Destination:=rw
sd.Copy Destination:=fd
bu.Copy Destination:=hu
zx.Copy Destination:=gx
op.Copy Destination:=wp
ty.Copy Destination:=ly
End Sub
A simple way to neatly take user input is to use the InputBox function
Sub ReadInputBox()
Dim readWorkbookLocation As String
readWorkbookLocation = InputBox("What is the name of the workbook you wish to read from?", "Workbook Select")
MsgBox workbookFile
End Sub
Yup. You can use the Application.GetOpenFilename to let the user choose the file name. For example
Option Explicit
Sub Sample()
Dim Ret
Dim Wb As Workbook
Dim ws As Worksheet
Ret = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*")
If Ret <> False Then
Set Wb = Workbooks.Open(Ret)
Set ws = Wb.Sheets("Sheet1")
With ws
'
'~~> Do whatever you want to do here with the worksheet
'
End With
End If
End Sub
EDIT: I just noticed that You have tagged it as excel-vba-mac as well. If you are doing this on Excel 2011 then see this link which shows how to use the Application.GetOpenFilename. The rest of the code remains as it is.
For these type of operations, I use a separate Excel file that contains the vb codes. (I'll call this file "Operation"). On a worksheet put the name of the source/destination file. Add buttons such as "Select Source", "Select Destination", which would prompt for a file but put the selected filename on the sheet only. Another button "Go" will do the actual operation using the files specified, something like:
If the columns to be copied seldom change, you can leave it inside VBA. If it changes from time to time or you need several versions, put it on the Operation worksheet too. If you need a more complex scenario, you can put the configuration on another worksheet in the sources/destination workbooks, so authors can specify the columns themselves.
As a suggestion for your code, use constants/variable for the filenames, to minimize typing when changing filenames manually. Also assign to variables the Workbook and Worksheet being operated on.
' OPERATIONS SHEET
Dim operWB as Workbook
Dim operWS as Worksheet
Set operWB = Application.ActiveWorkbook
Set operWS = operWB.ActiveSheet
' SOURCE
Dim srcFN as string
' HARDCODED: same as before
'srcFN = "WERT_2013_01_24.xlsx"
' OR get from Cell C2
srcFN = operWS.Cell( 2, 3 )
Dim srcWB as Workbook
Dim srcWS as Worksheet
Set srcWB = Workbooks.Open( srcFN )
Set srcWS = srcWB.Worksheets( 0 )
' DESTINATION
.... do the same ...
.... OPTION 1: COPY ....
Set srcRange = srcWS.Columns( "L" ) ' <-- or get from B10
Set dstRange = dstWS.Columns( "A" ) ' <-- or get from C10
srcRange.Copy Destination:=dstRange
....
.... OPTION 2: COPY AS LOOP ....
Dim currentRow As Integer
currentRow = 10
' keep going while B10, B11... is not empty
While operWS.Cells(currentRow, 2) <> ""
Set srcRange = srcWS.Columns( operWS.Cells(currentRow, 2) ) ' B10, B11 ...
Set dstRange = dstWS.Columns( operWS.Cells(currentRow, 3) ) ' C10, C11 ...
srcRange.Copy Destination:=dstRange
currentRow = currentRow + 1
Wend
You may use the following simple code to loop over all the files in the folder without knowing their names and quantity:
LoopFileNameExt = Dir(InputFolder & "*.xls?")
Do While LoopFileNameExt <> ""
'your code here
LoopFileNameExt = Dir
Loop
Wildcards are allowed in filemask. Good luck!