VBA cellextract for multiple xlsx files returning runtime error 9 - vba

At work, I receive a large number of PDF forms. Entry into the forms occurs in a table within the PDF. Specific entries in the PDF must be entered into an Excel sheet (referred to as the tracker from now on). It's very tedious to add each entry. This method is also prone to error.
I then determined that I could turn each PDF into a .xlsx file, keeping the table format. With cells to reference, I made a VLOOKUP formula to extract the exact info I needed for the tracker. I simply had to copy/paste the table range from the newly created converted .xlsx into my VLOOKUP extractor .xlsx, and the needed info would populate for me to paste into the tracker.
However, using this method, I would still need to convert multiple PDFs to .xlsx, open them one by one, paste the table into my extractor .xlsx, and then copy and paste the new extracted data into the tracker. So, still not quite efficient. I determined that I needed a macro.
The macro I found should loop through .xlsx files in a specified folder, opening them and searching for indicated cells. As you can see in the below macro, the cells aren't in any one range. I must extract values from specific cells.
Next, it should extract the values from the indicated cells and populate them as instructed in the sheet the macro was ran from.
However, I keep getting 'run-time error 9 subscript out of range' no matter what I do. Debug points to the following line of code as the reason for the error 9: Set OpenWorksheet = OpenWorkbook.Worksheets(SheetName)
I tried replacing SheetName in the offending line with Table1 only to get the same error. Tried Sheet1 but then get a run-time error 13.
I've been searching the net for a few hours, but I can't quite find a case similar to mine. Any help would be appreciated.
Macro is as follows:
Sub ExtractCells()
' local wb vars
Dim wb As Workbook
Dim ws As Worksheet
Dim MySheet As String
Dim r1 As Range
Dim r2 As Range
Dim r3 As Range
Dim r4 As Range
Dim r5 As Range
Dim r6 As Range
Dim r7 As Range
Dim r8 As Range
Dim r9 As Range
Dim r10 As Range
Dim r11 As Range
Dim r12 As Range
Dim i As Integer
' opened wb vars
Dim OpenWorkbook As Workbook
Dim OpenWorksheet As Worksheet
Dim SheetName As String
' looping params
Dim Directory As String
Dim FileSpec As String
Dim MyFile As String
' define looping params
Directory = "C:\MultiPD Test\Forms\" 'CHANGE THIS
FileSpec = ".xlsx" 'CHANGE THIS IF NECESSARY
MyFile = Dir(Directory & "*" & FileSpec)
SheetName = "Table1" 'CHANGE THIS
' set local vars
Set wb = ThisWorkbook
MySheet = "Sheet1" 'CHANGE THIS
Set ws = wb.Worksheets(MySheet)
' This is where data will begin to write
Set r1 = ws.Range("A1")
Set r2 = ws.Range("B1")
Set r3 = ws.Range("C1")
Set r4 = ws.Range("D1")
Set r5 = ws.Range("E1")
Set r6 = ws.Range("F1")
Set r7 = ws.Range("G1")
Set r8 = ws.Range("H1")
Set r9 = ws.Range("I1")
Set r10 = ws.Range("J1")
Set r11 = ws.Range("K1")
Set r12 = ws.Range("L1")
i = 0
' If there is one thing you take away from this, it should be the construct below i.e. how to loop through files
Do While MyFile <> ""
Set OpenWorkbook = Application.Workbooks.Open(Filename:="C:\MultiPD Test\Forms\*.xlsx", ReadOnly:=True)
Set OpenWorksheet = OpenWorkbook.Worksheets(SheetName)
' write data down col
With OpenWorksheet
r1.Offset(i, 0).Value = .Range("C4").Value
r2.Offset(i, 0).Value = .Range("C6").Value
r3.Offset(i, 0).Value = .Range("C8").Value
r4.Offset(i, 0).Value = .Range("C10").Value
r5.Offset(i, 0).Value = .Range("C12").Value
r6.Offset(i, 0).Value = .Range("C15").Value
r7.Offset(i, 0).Value = .Range("C16").Value
r8.Offset(i, 0).Value = .Range("C22").Value
r9.Offset(i, 0).Value = .Range("C35").Value
r10.Offset(i, 0).Value = .Range("C36").Value
r11.Offset(i, 0).Value = .Range("C37").Value
r12.Offset(i, 0).Value = .Range("C38").Value
End With
i = i + 1
MyFile = Dir
Loop
End Sub

As mentioned in the comments:
The first line that should throw Run-time error 1004: file "..." could not be found is this:
Application.Workbooks.Open(Filename:="C:\MultiPD Test\Forms\*.xlsx", ReadOnly:=True)
The next issue is that "Table1" is not a valid sheet name (it seems to be a ListObject name)
Once all sheets from the .XLSX files were renamed to Sheet1 your code works
The version bellow uses an array to reduce repetiton:
Option Explicit
Public Sub ExtractCellsFromMultiFiles()
Const SRC_COL = 3
Dim thisWS As Worksheet, wsName As String, srcRows As Variant
Dim foldr As String, srcFile As String, ext As String
srcRows = Array(4, 6, 8, 10, 12, 15, 16, 22, 35, 36, 37, 38)
wsName = "Sheet1" 'Not "Table1", which is probably a ListObject Table name
Set thisWS = ThisWorkbook.Worksheets(wsName)
foldr = "C:\MultiPD Test\Forms\"
ext = ".xlsx"
srcFile = Dir(foldr & "*" & ext)
Dim srcWB As Workbook, srcWS As Worksheet, i As Long, j As Long
i = 1
Application.ScreenUpdating = False
Do While Len(srcFile) > 0
Set srcWB = Workbooks.Open(Filename:=foldr & srcFile, ReadOnly:=True)
Set srcWS = srcWB.Worksheets(wsName)
For j = 1 To UBound(srcRows) + 1
thisWS.Cells(i, j).Value2 = srcWS.Cells(srcRows(j - 1), SRC_COL).Value2
Next
i = i + 1
srcWB.Close False
srcFile = Dir
Loop
Application.ScreenUpdating = True
End Sub
Output:
ColA ColB ColC ColD ColE ColF ColG ColH ColI ColJ ColK ColL
----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
S1C4 S1C6 S1C8 S1C10 S1C12 S1C15 S1C16 S1C22 S1C35 S1C36 S1C37 S1C38
S2C4 S2C6 S2C8 S2C10 S2C12 S2C15 S2C16 S2C22 S2C35 S2C36 S2C37 S2C38
S3C4 S3C6 S3C8 S3C10 S3C12 S3C15 S3C16 S3C22 S3C35 S3C36 S3C37 S3C38

Related

Run time error: 424 : Object required when I try to reach range and use range data

I am trying to highligh new excel the same way as old excel and data is large .So I saved the data in range and tried to do find, count if functions in range .But it keep showing "object not find error".I really don't get it since I defined the range object well. Here are part of my codes .I tried to debug by "RangSe1(1, 1).Activate" after I defined the RangSe1 object and it give me the 424 error even from here . I am really confused .
Sub Morningsmall()
Dim strfile As String
Dim iLastrow, iColor, iFind, iLastrow1, iLastrow2, iLastrow3, iLastrow4, iRow As Long
Dim RangSe1, RangSo1, RangSe2, RangSo2, RangS As Range
Dim wbLastday, wbToday As Workbook
Dim wsSettle1, wsSettle2, wsSophis1, wsSophis2 As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculate
.Calculation = xlCalculationManual
.DisplayStatusBar = False
End With
'Open yesterday's file
MsgBox "Open Yesterday's Settlement Report"
strfile = Application.GetOpenFilename
If strfile <> "False" Then Workbooks.Open strfile
Set wbLastday = ActiveWorkbook
Set wsSettle1 = wbLastday.Sheets("SettlementReport")
Set wsSophis1 = wbLastday.Sheets("Sophis")
iLastrow1 = wsSettle1.Cells(wsSettle1.Rows.Count, 1).End(xlUp).Row
iLastrow2 = wsSophis1.Cells(wsSophis1.Rows.Count, 1).End(xlUp).Row
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
RangSo1 = wsSophis1.Range("A1:AJ" & iLastrow2)
RangSe1(1, 1).Activate
...
...
...
For i = 2 To iLastrow3
iFind = RangSe2(i, 1)
'a = Application.WorksheetFunction.CountIf(Rang, iFind)
If Application.WorksheetFunction.CountIf(wsSettle1, iFind) > 0 Then
'range1.Find("test id", LookIn:=xlValues)
If RangSe1(wsSettle1.Cells.Find(what:=iFind).Row, 6) = RangSe2(i, 6) Then
iColor = RangSe1.Find(what:=iFind).Interior.Color
If iColor <> 16777215 Then
wsSettle2.Rows(i).Interior.Color = iColor
End If
End If
End If
...
...
...
Your lines saying
Dim RangSe1
'...
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
is equivalent to
Dim RangSe1 As Variant
'...
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1).Value
which will create a Variant array dimensioned as 1 To iLastrow1, 1 To 43. You can't use an Activate method on the (1, 1)th position of an array, because an array is not an object and therefore does not have methods or properties.
You have two major mistakes that are causing your code to not do what you expect:
1) You are not defining your variables correctly because:
Dim RangSe1, RangSo1, RangSe2, RangSo2, RangS As Range
is equivalent to :
Dim RangSe1 As Variant, RangSo1 As Variant, RangSe2 As Variant, RangSo2 As Variant, RangS As Range
You should use:
Dim RangSe1 As Range, RangSo1 As Range, RangSe2 As Range, RangSo2 As Range, RangS As Range
2) You are not using the Set keyword when assigning a reference to your Range objects so, for instance,
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
should be
Set RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)

How to remove extra empty text file created using vba excel macro wherein its filename is the cell in a sheet?

I'm just new in using excel vba macro. I am trying to create text file and use the cell values as name of individual text file. At the first place the value contains character and those character will be replaced. the only value will remain are all numbers. That function is working well. My problem is once I execute the create button, the program will create an extra text file which name is base on empty cell and no any input "D" as input in the text file. What I want is to create a text file without that extra text file created. below is my excel format and the code.
I have 3 column use as below:
LOG DATA INPUT BLOCK NAME
5687 D ASD
5689 D
5690 D
5692 D
5691 D
5688 D
4635 D
Correct result will create four text file:
abc-5687.req
abc-5689.req
abc-5690.req
abc-5692.req
Result with extra text file consider as wrong see below:
abc-.req <-- extra text file created
abc-5687.req
abc-5689.req
abc-5690.req
abc-5692.req
my code:
Private Sub CREATE_REQ_Click()
Dim myDataSheet As Worksheet
Dim myReplaceSheet As Worksheet
Dim myLastRow As Long
Dim myRow As Long
Dim myFind As String
Dim myReplace1 As String
Dim myReplace2 As String
Dim sExportFolder, sFN
Dim rArticleName As Range
Dim rDisclaimer As Range
Dim oSh As Worksheet
Dim oFS As Object
Dim oTxt As Object
' Specify name of Data sheet
Set myDataSheet = Sheets("Sheet1")
' Specify name of Sheet with list of replacements
Set myReplaceSheet = Sheets("Sheet2")
' Assuming list of replacement start in column A on row 2, find last entry in list
myLastRow = myReplaceSheet.Cells(Rows.Count, "A").End(xlUp).Row
Application.ScreenUpdating = False
' Loop through all list of replacments
For myRow = 2 To myLastRow
' Get find and replace values (from columns A and B)
myFind = myReplaceSheet.Cells(myRow, "A")
myReplace1 = myReplaceSheet.Cells(myRow, "B")
' Start at top of data sheet and do replacements
myDataSheet.Activate
Range("A2").Select
' Ignore errors that result from finding no matches
On Error Resume Next
' Do all replacements on column A of data sheet
Columns("A:A").Replace What:=myFind, Replacement:=myReplace1, LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
Next myRow
sExportFolder = "D:\TEST\REQ_FILES_CREATED_HERE"
Set oSh = Sheet1
Set oFS = CreateObject("Scripting.Filesystemobject")
For Each rArticleName In oSh.UsedRange.Columns("A").Cells
Set rDisclaimer = rArticleName.Offset(, 1)
If rArticleName = "" & "LOG DATA" Then
oTxt = False
Else
'Add .txt to the article name as a file name
sFN = "-" & rArticleName.Value & ".req"
Set oTxt = oFS.OpenTextFile(sExportFolder & "\" & ActiveSheet.Cells(2, 3) & sFN, 2, True)
oTxt.Write rDisclaimer.Value
oTxt.Close
End If
Next
'Reset error checking
On Error GoTo 0
Application.ScreenUpdating = True
MsgBox "Replacements complete! "
End Sub
For Each rArticleName In oSh.UsedRange.Columns("A").Cells
Set rDisclaimer = rArticleName.Offset(, 1)
If Not(rArticleName = "" Or rArticleName = "LOG DATA") Then
'Add .txt to the article name as a file name
sFN = "-" & rArticleName.Value & ".req"
Set oTxt = oFS.OpenTextFile(sExportFolder & "\" & ActiveSheet.Cells(2, 3) & sFN, 2, True)
oTxt.Write rDisclaimer.Value
oTxt.Close
End If
Next
Pretty close to a one line fix. You just need to fix the If. Once that's right you don't need the Else.

Can I use variable as sheetname (VBA)

I am a newcomer to VBA. I am trying to copy selected range from different workbooks and pasted to a target workbook with different sheetname correspondingly to the name of source file.
The code as below:
'open file
Sub RstChk()
Dim StrFileName As String
Dim StrFilePath As String
Dim TimeStr As String
Dim Version As Integer
Dim x As Workbook
Dim y As Workbook
Dim PstTgt As String
'define filename as array
Dim FN(10) As String
FN(1) = "CIO Wholesale"
FN(2) = "RMG"
FN(3) = "DCM"
FN(4) = "DivHeadOth"
FN(5) = "Runoff"
FN(6) = "Other Risk Subs"
FN(7) = "FIC"
FN(8) = "Treasury"
FN(9) = "Cash Equities"
FN(10) = "Global Derivatives"
'define file path
StrFilePath = "V:\RISKMIS\PUBLIC\apps\MORNING\RMU 1.5 Report\Consolidated\"
'define TimeStr
TimeStr = Format(Now() - 1, "mm-dd-yyyy")
Set y = Workbooks.Open("H:\Eform\Report_checking.xls")
'applying filename from array using loop
'----------------------------------------------------------------
For i = 1 To 10
'define changing file name with path & loop
For Version = 65 To 68
StrFileName = (StrFilePath & FN(i) & "_" & TimeStr & "_" & Chr(Version) & ".xls")
Set x = Workbooks.Open(StrFileName)
'-------------------------------------------------
If Chr(Version) = "A" Then
PstTgt = "A3"
ElseIf Chr(Version) = "B" Then
PstTgt = "E3"
ElseIf Chr(Version) = "C" Then
PstTgt = "I3"
Else
PstTgt = "M3"
End If
'copy the column and paste to report checking
y.Worksheets(FN(i)).PstTgt.Copy Destination = x.Sheets("Risk Summary").Range ("AA5:AC118")
Application.CutCopyMode = False
x.Close
Next Version
Next i
End Sub
I get error when I try to copy the range from source file (x) to target file (Y).
Run-time error '13', type mismatch
Just can't figure out what went wrong.
Thanks very much for your help.
Dan
You got this error because your variable PstTgt is a string and not a range "type mismatch"
If you look at the documentation of Range.Copy https://msdn.microsoft.com/en-us/library/office/ff837760.aspx
You have two choices :
Make PstTgt a range and referencing directly to the range in your endif
' Redefine PstTgt as a range
dim PstTgt as Range
' set value of PstTgt
If Chr(Version) = "A" Then
set PstTgt = y.Worksheets(FN(i)).Range("A3")
endif
...
' Copy the range where you want
PstTgt.Copy destination:=x.Sheets("Risk Summary").Range("AA5")
You keep your code like that and just correct your copy by adding Range
y.Worksheets(FN(i)).Range(PstTgt).Copy Destination = x.Sheets("Risk Summary").Range("AA5")

VBA: excel is closing, no error generated

I have a macro which I run on many file. The goal is to define a source and copy the value inside my file. It works fine for 30 source files but I recently have one that makes my excel crash, no error message nothing.
Here the code:
'dimensioning of the variables
'range and workbook
Dim Target_Area As Range
Dim Account_Number, Account_Description, Debit, Credit As Range
Dim General_Balance As Workbook
Dim Transform_file As Workbook
Dim Source_Range As Range
'technical var
Dim LastCell As Range
Dim LastCellNumber As Long
Dim Array_Position As Integer
Dim Worksheet_general_balance As Long
Dim Links As Variant
Dim address As String
'var used to adapt to the different trial balance
Dim startline, account_column, description_column, debit_column, credit_column As Integer
Dim column_to_test As String
Dim Target_Column(0 To 3) As Integer
'setting the variables
address = "blabla"
startline = 5
account_column = 1
description_column = 2
debit_column = 3
credit_column = 4
column_to_test = "A"
Target_Column(0) = 1
Target_Column(1) = 4
Target_Column(2) = 5
Target_Column(3) = 6
Worksheet_general_balance = 1
Set Transform_file = ActiveWorkbook
Set General_Balance = Workbooks.Open(address)
With General_Balance.Worksheets(Worksheet_general_balance)
Set LastCell = .Cells(.Rows.Count, column_to_test).End(xlUp)
LastCellNumber = LastCell.Row
End With
MsgBox "General TB sheet name: " & General_Balance.Worksheets(Worksheet_general_balance).Name
'3. save the required range from the source file
General_Balance.Worksheets(Worksheet_general_balance).Activate
Set Account_Number = General_Balance.Worksheets(Worksheet_general_balance).Range(Cells(startline, account_column), Cells(LastCellNumber, account_column))
Set Account_Description = General_Balance.Worksheets(Worksheet_general_balance).Range(Cells(startline, description_column), Cells(LastCellNumber, description_column))
Set Debit = General_Balance.Worksheets(Worksheet_general_balance).Range(Cells(startline, debit_column), Cells(LastCellNumber, debit_column))
Set Credit = General_Balance.Worksheets(Worksheet_general_balance).Range(Cells(startline, credit_column), Cells(LastCellNumber, credit_column))
'copying the value to the file
Transform_file.Activate
Transform_file.Worksheets("general balance").Range(Cells(6, Target_Column(0)), Cells(LastCellNumber - startline + 6, Target_Column(0))).Value = Account_Number.Value
Transform_file.Worksheets("general balance").Range(Cells(6, Target_Column(1)), Cells(LastCellNumber - startline + 6, Target_Column(1))).Value = Account_Description.Value
'up to this point, everything works well
'THE FOLLOWING TWO LINES EITHER ONE OF THEM MAKE EXCEL CRASH
Transform_file.Worksheets("general balance").Range(Cells(6, Target_Column(2)), Cells(LastCellNumber - startline + 6, Target_Column(2))).Value = Debit.Value
Transform_file.Worksheets("general balance").Range(Cells(6, Target_Column(3)), Cells(LastCellNumber - startline + 6, Target_Column(3))).Value = Credit.Value
General_Balance.Close
If I replace the range name Debit or Credit by Account_Number for example, the macro will finish, so i guess it's not about the destination.
I tried to put this code:
For Each cell In Debit.Cells
MsgBox cell.Value
Next cell
Before the problematic lines, and it goes through all the cells without any problems.
I can't find any reason why it's not working... any idea ?
First I think you should add some On Error to your code, including a
MsgBox Err.Description,,Err.Number.
My first guess is that you are trying to write to an already open/locked file.
Sub test()
On Error GoTo Hell
'Do lots of things
'...
Adios:
Exit Sub
Hell:
MsgBox Err.Description, vbCritical, "Error " & Err.Number
Resume Adios
Resume
End Sub
With the above sample, when you get the message box, press Ctrl+Break, move the yellow dot from the resume Adios to the Resume line, then press F8. Now you are on the line that caused the error.
Another way is to start your Sub in debug mode, and press F8 until it crashes (and remember where that was !).

copy paste from one file to several files

I would like to copy some cells from one file to several files. In order to do so,the macro will copy the range and open the several files in order to paste the values. I perform a loop in order to open each of the destination files (the begin of the name of each of the ouput file is the same but the extension differs from file to file : it is based on a range of cells called Name). The concatenation doesn't work well.
Thank you so much for your help!!
Sub update()
Application.ScreenUpdating = False
Dim wkbkorigin As Workbook
Dim wkbkdestination As Workbook
Dim originsheet As Worksheet
Dim destsheet As Worksheet
Dim i As Integer
Dim j As Integer
Dim nrow As Integer
Dim ncol As Integer
Dim Pathref As String
Dim Name As String
nrow = Range("names").Rows.Count
ncol = Range("Range").Columns.Count
'this is the path to the different files, the begin is the same but the extension will be added in the loop (the extentsion is based on the value in the range Name
Pathref = Range("Pathref").Value & "[yasmine_nouri]"
For i = 1 To nrow
Name = Range("Names").Cells(i, 1).Value
Set wkbkorigin = ActiveWorkbook
'here i set my destination file, the begin is the same but the extension is based on the value in the range Name : this concatenation doesn't work.
Set wkbkdestination = Workbooks.Open([& Pathref & Name & ".xlsb"])
Set originsheet = wkbkorigin.Worksheets("Completed_DS")
Set destsheet = wkbkdestination.Worksheets("sheet1")
originsheet.Range("D4:Q5").Copy
destsheet.Range("A1").PasteSpecial
wkbkdestination.Close SaveChanges:=True
Next i
End Sub
As follows up from comments, OP should change
Pathref = Range("Pathref").Value & "[yasmine_nouri]"
'...
Set wkbkdestination = Workbooks.Open([& Pathref & Name & ".xlsb"])
to
Pathref = Range("Pathref").Value & "yasmine_nouri"
'...
Set wkbkdestination = Workbooks.Open(Pathref & Name & ".xlsb")