VBA - Import Macro - How do i add to the current data when importing? - excel

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.

Related

How to name a worksheet?

I have a file (F) that contains several workbooks, each workbook has the same format. I do a conditional sum on each of the workbook under column conditions. I want to put the output within another workbook that contains one worksheet per workbook looped (contained within F).
I cannot find the good strategy to change the worksheet name in function of the looped workbook' name.
Set Output_tot_n = Workbooks("Final_Output").Sheet_name.Range("B7")
I got
Error 438 "Object doesn't support this property or method"
The whole code:
Sub Proceed_Data()
Dim FileSystemObj As Object
Dim FolderObj As Object
Dim fileobj As Object
Dim Sheet_name As Worksheet
Dim i, j, k As Integer
Dim wb As Workbook
Set FileSystemObj = CreateObject("Scripting.FileSystemObject")
Set FolderObj = FileSystemObj.GetFolder("C:\...\")
For Each fileobj In FolderObj.Files
Set wb = Workbooks.Open(fileobj.Path)
Set Output_tot_n = Workbooks("Final_Output").Sheet_name.Range("B7")
If wb.Name = "AAA_SEPT_2018" Then
Sheet_name = Worksheets("AAA")
End If
If wb.Name = "BBB_SEPT_2018" Then
Sheet_name = Worksheets("BBB")
End If
If wb.Name = "CCC_SEPT_2018" Then
Sheet_name = Worksheets("CCC")
End If
' conditional sum
With wb.Sheets("REPORT")
For i = 2 To .Cells(Rows.Count, 14).End(xlUp).Row
If .Cells(i, "O").Value = "sept" Then
k = .Cells(i, "M").Value
End If
j = j + k
k = 0
Next i
End With
Output_tot_n = j
j = 0
wb.Save
wb.Close
Next fileobj
End Sub
Workbooks is a collection (part of the actual Application-object). A collection in VBA can be accessed either by index number (index starts at 1) or by name. The name of an open Workbook is the name including the extension, in your case probably either Final_Output.xlsx or Final_Output.xlsm.
Sheets and Worksheets are collections within a Workbook, again accessed via index or name (the difference is that Worksheets contains "real" spreadsheets while Sheets may also contain other sheet types, eg charts).
So in your case, you want to access a Range of a specific sheet of a specific workbook. The workbook has a fixed name, while the sheet name is stored in a variable. You can write for example
dim sheetName as string, sheet as Worksheet, Output_tot_n as Range
sheetName = "AAA" ' (put your logic here)
set sheet = Workbooks("Final_Output.xlsm").Worksheets(Sheet_name)
set Output_tot_n = sheet.Range("B7")
or put all together (depending on your needs)
set Output_tot_n = Workbooks("Final_Output.xlsm").Worksheets(Sheet_name).Range("B7")
No it actually works. Thank you again for your answers.
the problem was just is important to put "AAA_SEPT_2018.xlsx"

Excel VBA - create column names using MS Project headers

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

VBA-Excel 2010 Macro Error "memeber or data method not found"

I know this is a super generic error but I am new to VBA / Macros and cant get past this.
I have an and excel workbook that has data I need to copy to another excel workbook.
The excel workbook that the data is copied to is on a network share and will be written to frequently.
here is my macro code:
Sub export()
Dim exportFile As String
Dim importSheet As String
Dim rowData As String
exportFile = "\\<server>\spd\_Spec_ParaData\data_import.xlsx"
importSheet = "OutPutValues"
importRange = "A2:ZZ2"
' Get the row from the workbook that we are running in
rowData = Workbooks().Worksheets(importSheet).Range(importRange)
' Not sure if this will work, or always overwrite the last row. May need to be .Row+1
newRow = Workbooks(exportFile).Worksheets(1).Cells(Rows.Count, "A").End(xlUp).Row
exportRange = "A" & (newRow + 1) & ":ZZ" & (newRow + 1)
' Assuming Workbooks() gets the current workbook.
Workbooks(exportFile).Sheets(exportSheet).Range(exportRange) = Workbooks().Sheets(importSheet).Range(importRange)
End Sub
My error is poping up on the rowData=Workbooks(exportFile).Worksheets
Can someone help me figure out what I am doing wrong?
Thank you,
Jennifer
Try your code with the following modifications, I'm just opening the workbook and referencing the worksheet (I guess the problem is that). I'm closing the workbook straight after.
Sub export()
Dim exportFile As String
Dim importSheet As String
Dim rowData As String
Dim wb As Workbook
Dim ws1 As Worksheet, ws2 As Worksheet
exportFile = "\\<server>\spd\_Spec_ParaData\data_import.xlsx"
importSheet = "OutPutValues"
importRange = "A2:ZZ2"
'Open your workbook and point to your spreadsheet
Set wb = Workbooks.Open(exportFile)
Set ws1 = wb.Sheets(importSheet)
' Get the row from the workbook that we are running in
rowData = wb.ws.Range(importRange)
' Not sure if this will work, or always overwrite the last row. May need to be .Row+1
newRow = wb.Worksheets(1).Cells(Rows.Count, "A").End(xlUp).Row
exportRange = "A" & (newRow + 1) & ":ZZ" & (newRow + 1)
'NOTE: consider definying the variable "exportSheet", I will do it just for example purpose
Dim exportSheet As String: exportSheet = "InputValues"
Set ws2 = wb.Sheets(exportSheet)
' Assuming Workbooks() gets the current workbook.
wb.ws2.Range(exportRange) = wb.ws1.Range(importRange)
wb.Close
End Sub

Excel VBA import of various excel files to master sheet

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

Copying specific columns from several workbooks to one master workbook, without constantly editing code

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!

Resources