VBA excel: Copy specific cells and columns from multiple files - excel

I am trying to copy a specific cell and 3 columns from multiple files into a single column on another spreadsheet.
The part called "import" simply allows to select multiple files. The part "Datacopy" should copy the desired values.
Sub import()
Dim oFileDialog As FileDialog
Set oFileDialog = Application.FileDialog(msoFileDialogFilePicker)
oFileDialog.AllowMultiSelect = True
oFileDialog.InitialFileName = "C:\Users\L18938\Desktop\New_folder" ' can set your default directory here
oFileDialog.Show
Dim iCount As Integer
For iCount = 1 To oFileDialog.SelectedItems.Count
Call Datacopy(oFileDialog.SelectedItems(iCount))
Next
End Sub
Public Function Datacopy(strPath As String)
Dim filePath As String
Dim FileNum As Integer
filePath = strPath
Dim startDate As String
If Range("A2").Value <> "" Then
Range("A1").End(xlDown).Offset(1, 0).Select
Else:
Range("A1:A" & Range("A" & Rows.Count).End(xlUp).Row).Offset(1, 0).Select
End If
currentRow = 0
rowNumber = 0
Open filePath For Input As #1
'EOF(1) checks for the end of a file
Do Until EOF(1)
If rowNumber = 0 Then
startDate = lineitems(2)
End If
If rowNumber > 18 And item <> "" Then
ActiveCell.Offset(currentRow, 0) = startDate
ActiveCell.Offset(currentRow, 1) = lineitems(0)
ActiveCell.Offset(currentRow, 2) = lineitems(1)
ActiveCell.Offset(currentRow, 3) = lineitems(2)
currentRow = currentRow + 1
End If
End If
Next item
rowNumber = rowNumber + 1
Loop
Close #1
End Function
When I run it I get the error "sub or function not defined".
The cells I am targeting are:
C1 -> is a date, different in each file, to be copied in column A
Columns A18:A, B18:B, C18:C -> are data to be copied in columns B, C, D respectively.
It is important to copy multiple files, as I have more than 180.

Your problem is "startDate = lineitems(2)". There's nothing in your code that assigns any kind of value to "lineitems".

Related

Dynamically Named range in excel vba

I am trying to copy named range in excel from one sheet to another, this works superb when I am using a static name. However now I would like to get the named range from a userform list box, and I am unsure how to do this. My copy function takes in the row number and I need to find this row number based on the string coming from the Listbox. If the listbox says Bolts the named range would be _OutputBolts which is refered to A123.
Call copyRows(ws, ThisWorkbook.Sheets("Templates").[_DrawingInputs].Row)
Call copyRows(ws, ThisWorkbook.Sheets("Templates").[_GeneralInputs].Row)
Call copyRows(ws, ThisWorkbook.Sheets("Templates").[_MaterialData].Row)
If GUI.ListBox_AdditionalComponents.ListCount > 0 Then
For i = 0 To GUI.ListBox_AdditionalComponents.ListCount - 1
namedRange = "[_Output" & GUI.ListBox_AdditionalComponents.List(i) & "]"
Call copyRows(ws, ThisWorkbook.Sheets("Templates").namedRange.Row)
Next i
End If
The copy procedure
Public Sub copyRows(ByRef shNew As Worksheet, startRow As Integer)
Dim i, j As Integer
Dim wsTemplates As Worksheet
Dim temp As Variant
Dim rowOverview As Integer
Dim lastCol As Integer
On Error Resume Next
Set wsTemplates = ThisWorkbook.Sheets("Templates")
i = startRow ' Where to copy from in templates
j = getLastRow(shNew, 1) 'Where to copy to, i.e append
If j > 2 Then
j = j + 2
End If
Do While wsTemplates.Cells(i, 1) <> ""
'copy the old range
wsTemplates.Rows(i).EntireRow.Copy
'paste it
shNew.Rows(j).EntireRow.Select
shNew.Paste
'format height
temp = wsTemplates.Rows(i).Height
shNew.Rows(j).RowHeight = CInt(temp)
' fill in the value from the GUI
temp = ""
temp = GUI.Controls("TextBox_" & Replace(shNew.Cells(j, 1).value, " ", "")).value
If temp = "" Then
temp = GUI.Controls("ComboBox_" & Replace(shNew.Cells(j, 1).value, " ", "")).value
End If
If temp <> "" Then
shNew.Cells(j, 4).value = temp
End If
'hyperlink drawing
If shNew.Cells(j, 1).value = "Drawing Name" Then
Call createHyperLink(shNew, j, 4, shNew.Cells(j, 4).value, GetFileNameWithOutExtension(getFilenameFromPath(shNew.Cells(j, 4).value)), shNew.Cells(j, 4).value)
End If
'update counters
i = i + 1
j = j + 1
Loop
' Format column widths, seems to be bug in this one...Maybe move out due to the fact we could do this once..
lastCol = getLastColumn(wsTemplates, 1)
For i = 1 To lastCol
temp = wsTemplates.Cells(1, i).Width
shNew.Columns(i).ColumnWidth = temp
Next i
End Sub
Solved by using Range(address), see comment

VBA: import multiple csv file into an existing table

I want to import multiple csv files at the bottom of an existing table. However, when importing the files, it always excludes the first row of the list of each file. The first row of the list differs from the first row of the spreadsheet because in between there are other rows that are not needed (e.g. titles, empty rows...). Resuming: if I upload 5 files, it miss the first desired row of each of the 5 files.
This is the code:
Private Sub Import_auction_offers_Click()
Dim strSourcePath As String
Dim strFile As String
Dim Cnt As Long
'Change the path to the source folder accordingly
strSourcePath = "C:\Users\L18944\Desktop\example"
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
strFile = Dir(strSourcePath & "*.csv")
Do While Len(strFile) > 0
Cnt = Cnt + 1
Open strSourcePath & strFile For Input As #1
If Range("F2").Value <> "" Then
Range("F1").End(xlDown).offset(1, 0).Select
Else:
Range("F1:F" & Range("F" & Rows.Count).End(xlUp).Row).offset(1, 0).Select
End If
currentRow = 0
rowNumber = 0
'EOF(1) checks for the end of a file
Do Until EOF(1)
Line Input #1, lineFromFile
fileStr = Split(lineFromFile, vbLf)
Dim item As Variant
For Each item In fileStr
'For item = LBound(fileStr) To UBound(fileStr)
lineitems = Split(item, ";")
'Debug.Print (item)
If rowNumber = 1 Then
startDate = lineitems(6)
End If
If rowNumber > 3 And item <> "" Then
If Not doesOfferExist(CStr(lineitems(2))) Then
ActiveCell.offset(currentRow, 0) = startDate
ActiveCell.offset(currentRow, 1) = lineitems(4)
ActiveCell.offset(currentRow, 2) = lineitems(3)
ActiveCell.offset(currentRow, 3) = CDbl(lineitems(6))
ActiveCell.offset(currentRow, 4) = CDbl(lineitems(7))
ActiveCell.offset(currentRow, 5) = lineitems(8)
ActiveCell.offset(currentRow, 6) = lineitems(1)
ActiveCell.offset(currentRow, 7) = lineitems(2)
ActiveCell.offset(currentRow, 8) = "New"
currentRow = currentRow + 1
End If
End If
rowNumber = rowNumber + 1
Next item
Loop
Close #1
Name strSourcePath & strFile As strSourcePath & strFile
strFile = Dir
Loop
Application.ScreenUpdating = True
If Cnt = 0 Then _
MsgBox "No CSV files were found...", vbExclamation
End Sub
Does anyone understand why it miss the first line of each imported list?
Thank you in advance
I didn't go through your ImportAuctionOffers code, but I'm assuming you are finding the new starting row for each file.
This code will let you pick your files (and set your initial directory). Then loop through all the selected items, calling your ImportAuctionOffers procedure for each file.
Sub test()
Dim oFileDialog As FileDialog
Set oFileDialog = Application.FileDialog(msoFileDialogFilePicker)
oFileDialog.AllowMultiSelect = True
oFileDialog.InitialFileName = "C:\Temp" ' can set your default directory here
oFileDialog.Show
Dim iCount As Integer
For iCount = 1 To oFileDialog.SelectedItems.Count
Call ImportAuctionOffers(oFileDialog.SelectedItems(iCount))
Next
End Sub
Update:
For your second issue: Not reading the first data line is likely due to the if statements with RowNumber.
rowNumber=0
Do ...
if RowNumber = 1 Then ...
if RowNumber > 3 ...
RowNumber = RowNumber + 1
loop
Your code is not going to enter either of your if statements when RowNumber equals 0, 2, or 3. You probably just need to change your > 3 to either > 2, or >= 3.

Searching multiple tables on the same sheet with the column in varying locations and copying them to a different sheet

Hopefully the title is clear. I am trying to search through multiple tables on a single sheet. The information I am looking for is the same for all of the tables, just that the corresponding column is located in different spots (e.g. in one table the column I want to search is in I, while for another table it could be in O.) which makes it a bit more challenging for me.
I want to search through each column that has the same title (Load Number) and depending on its value, copy that entire row over to a sheet that corresponds with that value.
Below is what I have so far in VBA as well as a picture to hopefully clarify my issue.
Any help/advice is appreciated!
http://imgur.com/a/e9DyH
Sub Load_Number_Finder()
Dim ws As Worksheet
Dim i As Integer
Dim j As Integer
j = 1
Set ws = Sheets.Add(After:=Sheets("Master"))
ws.Name = ("Test Load " & j)
i = 1
Sheets("Master").Select
For Each cell In Sheets("Master").Range("M:M")
If cell.Value = "1" Then
j = 1
'Set WS = Sheets.Add(After:=Sheets("Master"))
'WS.Name = ("Test Load " & j)
matchRow = cell.Row
Rows(matchRow & ":" & matchRow).Select
Selection.Copy
Sheets("Test Load " & j).Select
ActiveSheet.Rows(i).Select
ActiveSheet.Paste
Sheets("Master").Select
i = i + 1
ElseIf cell.Value = "" Then
' 2, 3, 4, 5, cases
Else
' Something needs to go here to catch when it doesnt have a load number on it yet
End If
' Err_Execute:
' MsgBox "An error occurred."
Next
End Sub
Try this function. This should work for you. Let me know what the results are with your sheet. I made a mock up sheet and tested it, it worked. I can make changes if this is not exactly what you are looking for.
Option Explicit
Sub copyPaste()
Dim rowCount, row_ix, temp, i As Integer
Dim TD_COL_IX As Integer
Dim td_value As String
Dim td_values() As String
rowCount = Worksheets("Master").Cells(Rows.Count, "A").End(xlUp).Row
For row_ix = 1 To rowCount
temp = isNewTable(CInt(row_ix))
If temp > 0 Then
TD_COL_IX = temp
ElseIf TD_COL_IX > 0 Then
td_value = Worksheets("Master").Cells(row_ix, TD_COL_IX)
If Not td_value = "" Then
td_values = Split(td_value, " ")
For i = 0 To UBound(td_values)
If Not sheetExists("Test Load " & td_values(i)) Then
Sheets.Add.Name = "Test Load " & td_values(i)
End If
If Worksheets("Test Load " & td_values(i)).Cells(1, 1).Value = "" Then
Worksheets("Master").Range(Worksheets("Master").Cells(row_ix, 1), Worksheets("Master").Cells(row_ix, TD_COL_IX - 1)).Copy _
Destination:=Worksheets("Test Load " & td_values(i)).Cells(1, 1)
Else
Dim rowCount_pasteSheet As Integer
rowCount_pasteSheet = Worksheets("Test Load " & td_values(i)).Cells(Rows.Count, "A").End(xlUp).Row
Worksheets("Master").Range(Worksheets("Master").Cells(row_ix, 1), Worksheets("Master").Cells(row_ix, TD_COL_IX - 1)).Copy _
Destination:=Worksheets("Test Load " & td_values(i)).Cells(rowCount_pasteSheet + 1, 1)
End If
Next i
End If
End If
Next row_ix
End Sub
Function isNewTable(row_ix As Integer) As Integer
Dim colCount, col_ix As Integer
colCount = Worksheets("Master").Cells(row_ix, Columns.Count).End(xlToLeft).Column
For col_ix = 1 To colCount
If Not IsError(Worksheets("Master").Cells(row_ix, col_ix).Value) Then
If Worksheets("Master").Cells(row_ix, col_ix).Value = "LD #" Then
isNewTable = col_ix
Exit Function
End If
End If
Next col_ix
isNewTable = 0
End Function
' ####################################################
' sheetExists(sheetToFind As String) As Boolean
'
' Returns true if the sheet exists, False otherwise
' ####################################################
Public Function sheetExists(sheetToFind As String) As Boolean
Dim sheet As Worksheet
sheetExists = False
For Each sheet In Worksheets
If sheetToFind = sheet.Name Then
sheetExists = True
Exit Function
End If
Next sheet
End Function

VBA dynamic ListBox

Here is my code:
Private Sub UserForm_Initialize()
Dim MyFolder As String
Dim MyFile As String
Dim j As Integer
Dim Funds(1000)
CD_Date = Cells(1, 4)
Range("A2").Select
i = 1
Do
Funds(i) = UCase(ActiveCell.Value)
i = i + 1
ActiveCell.Offset(1, 0).Select
Loop Until ActiveCell.Value = ""
MyFolder = "C:\windows\"
r = 0
For k = 1 To i - 1
MyFile = Dir$(MyFolder & "*" & Funds(k) & "*")
Do While MyFile <> ""
datka = FileDateTime(MyFolder & MyFile)
If Format(datka, "yymmdd") = Format(CD_Date, "yymmdd") Then
With UserForm1.ListBox1
.AddItem
.List(r, 0) = Funds(k)
.List(r, 1) = MyFile
r = r + 1
End With
End If
MyFile = Dir$
Loop
Next k
Range("A2").Select
End Sub
Code works perfectly, but it doesn't change dynamically when I move CD_Date for prior day or current - 2. It always add item for entered date and only for first run. When I change date in cell it always return me list from first initialize. It resets when I close file and open it again, each time for different date. Is it possible to modify my code that it will be filling dynamically after I change CD_Date or when someone add file to the folder?? I want to avoid closing and opening macro over and over just to get actual data :(
You could add in a loop to remove all items from the ListBox before the point in your code where items are added to effectively refresh it each time. To do this you are looking for something like:
With UserForm1.ListBox1
For i = 1 to .ListCount
.RemoveItem(0)
Next i
End With
In your code it seems like each time you open the form you only want one item in the ListBox, so although the loop here is unnecessary its a good practice to remember. Try placing this in your module just before you add the item:
Private Sub UserForm_Initialize()
Dim MyFolder As String
Dim MyFile As String
Dim j As Integer
Dim Funds(1000)
CD_Date = Cells(1, 4)
Range("A2").Select
i = 1
Do
Funds(i) = UCase(ActiveCell.Value)
i = i + 1
ActiveCell.Offset(1, 0).Select
Loop Until ActiveCell.Value = ""
MyFolder = "C:\windows\"
r = 0
For k = 1 To i - 1
MyFile = Dir$(MyFolder & "*" & Funds(k) & "*")
Do While MyFile <> ""
datka = FileDateTime(MyFolder & MyFile)
If Format(datka, "yymmdd") = Format(CD_Date, "yymmdd") Then
With UserForm1.ListBox1
For i = 1 to .ListCount 'Here
.RemoveItem(0)
Next i
.AddItem
.List(r, 0) = Funds(k)
.List(r, 1) = MyFile
r = r + 1
End With
End If
MyFile = Dir$
Loop
Next k
Range("A2").Select
End Sub

VBA Coding to pull data

I have 50 .xls files saved on a shared drive by the name of users. Eg: "Rahul Goswami.xls", "Rohit Sharma.xls", etc.
Each Excel file contains 2 worksheets: "Case Tracker" and "Pending Tracker".
In the "Case Tracker" worksheet users put their daily data/ daily production.
I wanted VBA code to pull the entire "Case Tracker" worksheet from all 50 Excel files in one separate Excel workbook, one below the other.
Currently I am copy-pasting the data from the Excel files to the master workbook to "Sheet1".
Can there be something where I put the date and the data will come automatically for that date from all the 50 files?
Column A to J contains the data provided below. This example is given for 1 user.
Date Advisor Userid BP URN Stage Case Type Previous Status Current status Category
10-Apr Rahul Goswami goswami 123456 98765431 1 URN New Pend abc
Sub Beachson()
Dim z As Long, e As Long, d As Long, G As Long, h As Long Dim f As String
d = 2
Cells(1, 1) = "=cell(""filename"")"
Cells(1, 2) = "=left(A1,find(""["",A1)-1)"
Cells(2, 1).Select
f = Dir(Cells(1, 2) & "*.xls")
Do While Len(f) > 0
## Heading ##
ActiveCell.Formula = f
ActiveCell.Offset(1, 0).Select
f = Dir()
Loop
z = Cells(Rows.Count, 1).End(xlUp).Row
For e = 2 To z
If Cells(e, 1) <> ActiveWorkbook.Name Then
Cells(d, 2) = Cells(e, 1)
Cells(1, 4) = "=Counta('" & Cells(1, 2) & "[" & Cells(e, 1) & "]Case Tracker'!I:I)"
For h = 10 To Cells(1, 4)
For G = 1 To 10
Cells(1, 3) = "='" & Cells(1, 2) & "[" & Cells(e, 1) & "]Case Tracker'!" & Chr(G + 64) & h
Cells(d, G + 2) = Cells(1, 3)
Next G
d = d + 1
Next h
End If
d = d + 1
Next e
MsgBox "collating is complete."
End Sub
I would avoid storing information in sheet, then going to VBA, then again to sheet, etc.
As for your problem of not being able to pull data when a file is open, I would suggest creating another instance of Excel.Application and opening files from it in ReadOnly mode.
This is the code which worked for me (the ability to find particular dates is also implemented):
Sub Beachson2()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
Dim App As Object
Set App = CreateObject("Excel.Application")
Dim wsSource As Worksheet
Dim sFold As String
sFold = ThisWorkbook.Path & "\"
Dim sFile As String
Dim i As Long, j As Long
Dim cell As Range
' Setting date
Dim sInput As String, dInput As Date
sInput = Application.InputBox("Enter A Date")
If IsDate(sInput) Then
dInput = DateValue(sInput)
Else
MsgBox "Invalid date. Exiting..."
Exit Sub
End If
Application.ScreenUpdating = False
' Pulling data
i = 1
sFile = Dir(sFold & "\*.xls")
Do While sFile <> ""
If sFile <> sFold & ThisWorkbook.Name Then
Set wsSource = App.Workbooks.Open(Filename:=sFold & sFile, ReadOnly:=True).Sheets("Case Tracker")
For Each cell In wsSource.Range("A1:A" & wsSource.UsedRange.Rows.Count)
If cell.Value = CStr(dInput) Then
With ws.Cells(Rows.Count, 1).End(xlUp)
If IsEmpty(.Value2) Then
.Value2 = sFile
ElseIf .Value2 <> sFile Then
.Offset(1).Value2 = sFile
Else
'do nothing
End If
End With
If ws.Cells(Rows.Count, 2).End(xlUp).Value2 <> sFile Then
ws.Cells(i, 2).Value2 = sFile
End If
For j = 3 To 12
ws.Cells(i, j).Value = wsSource.Cells(cell.Row, j - 2).Value
Next
i = i + 1
End If
Next
wsSource.Parent.Close
End If
sFile = Dir()
Loop
Application.ScreenUpdating = True
App.Quit
MsgBox "collating is complete."
Set App = Nothing
End Sub
The code is stored in the master file.
Even in the code there is no one specific Date format defined, but I still think it is capable of causing problems. If you find problems regarding date formats, please post your used date format.

Resources