Ken
Ken

Reputation: 1

VBA Program Results Not Going to Current Worksheet

I'm new to VBA. Based on information I've found in this forum, I've been able to successfully create a functional macro but with a few issues remaining. The purpose of the macro is to build a dataset from a directory full of xls* files. Works great mostly. Many thanks for those who posted what I started with.

The problem is that each time I execute, it creates the answer set in Sheet1 of a new Workbook. I would like the answer set to go either into the current sheet of the current workbook or alternatively go into the "Data" sheet of a specific workbook. In this case, I'd really like for the answer set to be in the xlsm file where the macro is located. I've not been able to locate a working solution. More accurately, I don't understand why this isn't going to my current worksheet by default as documentation seems to indicate that it should.

One other question. In the following code, it is relatively simple for a neophyte to follow/adjust the Sub code. However, can someone explain (generally) the Private Function code? Though it works, I'm having difficulty understanding technically what it is doing.

Sub ReadDataFromAllWorkbooksInFolder()
    Dim FolderName As String, wbName As String, r As Long, cValue As Variant
    Dim fs, f, s
    Dim wbList() As String, wbCount As Integer, i As Integer, Lead As Integer
    Dim CheckIN As Date, CheckOUT As Date
    Dim Total As Currency, Deposit As Currency, Balance As Currency, STax As Currency, CTax As Currency, TTax As Currency
    Dim Rent As Currency, Pet As Currency, Cleaning As Currency, HotTub As Currency
    Dim BookDate As Date, Origin As Date



    FolderName = "C:\Users\Ken\Documents\Personal\Ferguson House\Contracts\Sample"
    ' create list of workbooks in foldername' --- Comment
    wbCount = 0
    wbName = Dir(FolderName & "\" & "*.xls*")
    While wbName <> ""
        wbCount = wbCount + 1
        ReDim Preserve wbList(1 To wbCount)
        wbList(wbCount) = wbName
        wbName = Dir
    Wend
    If wbCount = 0 Then Exit Sub
        ' get values from each workbook' --- Comment
        r = 1
        Workbooks.Add
        For i = 1 To wbCount
            r = r + 1
            House = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "I1")
            Name = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c2")
            Address = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c3")
            Phone = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c4")
            Fax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c5")
            Email = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c6")
            Total = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d10")
            Deposit = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d11")
            Balance = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d12")
            STax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c55")
            CTax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c56")
            TTax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c57")
            Rent = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c51")
            Pet = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i16")
            Cleaning = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i14")
            HotTub = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i15")
            CheckIN = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i2")
            CheckOUT = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "g44")
            NIGHTS = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i3")
            BookDt = FolderName & "\" & wbList(i)
            BookDate = FileDateTime(BookDt)
            Origin = Int(BookDate)
            Lead = CheckIN - Origin
            Cells(r, 1).Value = wbList(i)
            Cells(r, 2).Value = House
            Cells(r, 3).Value = Name
            Cells(r, 4).Value = Address
            Cells(r, 5).Value = Phone
            Cells(r, 6).Value = Fax
            Cells(r, 7).Value = Email
            Cells(r, 8).Value = Total
            Cells(r, 9).Value = Deposit
            Cells(r, 10).Value = Balance
            Cells(r, 11).Value = STax
            Cells(r, 12).Value = CTax
            Cells(r, 13).Value = TTax
            Cells(r, 14).Value = Rent
            Cells(r, 15).Value = Pet
            Cells(r, 16).Value = Cleaning
            Cells(r, 17).Value = HotTub
            Cells(r, 18).Value = CheckIN
            Cells(r, 19).Value = CheckOUT
            Cells(r, 20).Value = NIGHTS
            Cells(r, 21).Value = Origin
            Cells(r, 22).Value = Lead

        Next i

        'Create Headers
        Range("$A$1").Value = "Contract"
        Range("$B$1").Value = "House #"
        Range("$C$1").Value = "Name"
        Range("$D$1").Value = "Address"
        Range("$E$1").Value = "Phone"
        Range("$F$1").Value = "Fax"
        Range("$G$1").Value = "Email"
        Range("$H$1").Value = "Total"
        Range("$I$1").Value = "Deposit"
        Range("$J$1").Value = "Balance"
        Range("$K$1").Value = "St Tax"
        Range("$L$1").Value = "Cty Tax"
        Range("$M$1").Value = "Tot Tax"
        Range("$N$1").Value = "Rent Only"
        Range("$O$1").Value = "Pet Fee"
        Range("$P$1").Value = "Cleaning"
        Range("$Q$1").Value = "Hot Tub"
        Range("$R$1").Value = "Check In"
        Range("$S$1").Value = "Check Out"
        Range("$T$1").Value = "Nights"
        Range("$U$1").Value = "Book Dte"
        Range("$V$1").Value = "Lead Time"
        Range("A1:V1").Font.Bold = True

End Sub

Private Function GetInfoFromClosedFile(ByVal wbPath As String, _
    wbName As String, wsName As String, cellRef As String) As Variant
    Dim arg As String
    GetInfoFromClosedFile = ""
    If Right(wbPath, 1) <> "\" Then wbPath = wbPath & "\"
    If Dir(wbPath & "\" & wbName) = "" Then Exit Function
    arg = "'" & wbPath & "[" & wbName & "]" & _
        wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
    On Error Resume Next
    GetInfoFromClosedFile = ExecuteExcel4Macro(arg)
End Function

Upvotes: 0

Views: 71

Answers (3)

Sgdva
Sgdva

Reputation: 2800

The Function is a good approach -what is doing is basically saving you the time of open the desired WB and instead retrieving the data straight forward-.
In a "normal" process you would need to
1. Open the WB
2. Select the sheet
3. Get the desired value
4.Close the WB
This functions relies on the fact that you can type a formula in Excel that retrieves the desired value from a closed wb. You may try for yourself in ExcelSheet ='C:\MyUser\Documents\[DesiredWB.xls]Sheet1'!$A$2 ->this is faster than doing the 4 steps mentioned above isn't?
However, this seems like a "quick fix".
I faced a similar situation and came with this solution that basically does the same,but, has more error handling. -I'll do the example for "House"
1. First, verify the desired sheet exists in the WB:

Function SheetExistsFDB(ShtName$, WbPath$) As Boolean
Dim GV, ParentFolder$, FileName$, PD%
'Split to folder and file name

PD = InStrRev(WbPath, "\")
ParentFolder = Left(WbPath, PD - 1)
FileName = Mid(WbPath, PD + 1)


' also can be used to get the value RV from a specified Row Col if you need it
GV = ExecuteExcel4Macro("'" & ParentFolder & "\[" & FileName & "]" & ShtName & "'!R1C1")
SheetExistsFDB = CStr(GV) <> "Error 2023"
' MsgBox CStr(GV)
End Function


2. Use this formula to just type the formula as described:

Sub WriteFormulasvalues(iFilePath As String, iFilename As String, iSheet As String, iRC As String, iRange As Range, Optional AdditionalText As String)
myFormula = "='" & iFilePath & "[" & iFilename & "]" & iSheet & "'!" & iRC & ""
    With iRange
    .Formula = myFormula
    .Value = AdditionalText & .Value
    End With
End Sub

Since all your variables use the same name sheet, I'd use something like

For i = 1 To wbCount
Dim RealPath
RealPath = FolderName & wbList(i)
If SheetExistsFDB("Contract", RealPath) = True Then ' 1. If SheetExistsFDB(RealPath, "Contract") = True
        r = r + 1
        'House used as example correct others
        Call WriteFormulasvalues(FolderName, wbList(i), "Contract", "R1C9", Cells(r, 2)) 'I used RC format so according to your code I1= R1C9

        Name = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c2")
        Address = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c3")
        Phone = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c4")
        Fax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c5")
        Email = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c6")
        Total = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d10")
        Deposit = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d11")
        Balance = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "d12")
        STax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c55")
        CTax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c56")
        TTax = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c57")
        Rent = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "c51")
        Pet = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i16")
        Cleaning = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i14")
        HotTub = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i15")
        CheckIn = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i2")
        CheckOut = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "g44")
        NIGHTS = GetInfoFromClosedFile(FolderName, wbList(i), "Contract", "i3")
        BookDt = FolderName & "\" & wbList(i)
        BookDate = FileDateTime(BookDt)
        Origin = Int(BookDate)
        Lead = CheckIn - Origin
        Cells(r, 1).Value = wbList(i)
        'Cells(r, 2).Value = House no longer needed since WriterFormulas does it
        Cells(r, 3).Value = Name
        Cells(r, 4).Value = Address
        Cells(r, 5).Value = Phone
        Cells(r, 6).Value = Fax
        Cells(r, 7).Value = Email
        Cells(r, 8).Value = Total
        Cells(r, 9).Value = Deposit
        Cells(r, 10).Value = Balance
        Cells(r, 11).Value = STax
        Cells(r, 12).Value = CTax
        Cells(r, 13).Value = TTax
        Cells(r, 14).Value = Rent
        Cells(r, 15).Value = Pet
        Cells(r, 16).Value = Cleaning
        Cells(r, 17).Value = HotTub
        Cells(r, 18).Value = CheckIn
        Cells(r, 19).Value = CheckOut
        Cells(r, 20).Value = NIGHTS
        Cells(r, 21).Value = Origin
        Cells(r, 22).Value = Lead
End If ' 1. If SheetExistsFDB(RealPath, "Contract") = True
    Next i
Sub WriteFormulasvalues(iFilePath As String, iFilename As String, iSheet As String, iRC As String, iRange As Range, Optional AdditionalText As String)
myFormula = "='" & iFilePath & "[" & iFilename & "]" & iSheet & "'!" & iRC & ""
    With iRange
    .Formula = myFormula
    .Value = AdditionalText & .Value
    End With
End Sub

Upvotes: 0

Brad
Brad

Reputation: 12245

Any time you use a reference like Cells(r, 1).Value or Range("$K$1").Value what you are implicitly saying is you want ActiveSheet.Cells(r, 1).Value or ActiveSheet.Range("$K$1").Value.

The solution to this is to use fully qualified references. Don't let Excel assume anything.

So instead of just doing

Workbooks.Add

Do

Dim myDestinationSheet As Worksheet
Dim myDestinationWorkbook As Workbook
Set myDestinationWorkbook = Workbooks.Add
Set myDestinationSheet = myDestinationWorkbook.Sheets(1)
myDestinationSheet.Name = "Data"
myDestinationSheet.Cells(1,1).value = House

You should use this technique to resolve any possible ambiguity in object references on every line of code you write. Even if you use ActiveSheet like might be the default it is best to use it explicitly.

Upvotes: 0

David Zemens
David Zemens

Reputation: 53623

Workbooks.Add is creating a new workbook.

The un-qualified Cells object, where you're assigning data to the "current" sheet, will always revert to whatever worksheet is active at run-time. Adding a workbook makes that book Active, and by default the Sheet1 object will be active in that workbook.

I suspect that simply getting rid of Workbooks.Add will resolve the problem, but you may need further tweak to explicitly activate the sheet on which you desire the code to be placed, such as:

    With ThisWorkbook.Sheets("YOUR SHEET NAME") ' ## MODIFY AS NEEDED!
        .Cells(r, 1).Value = wbList(i)
        .Cells(r, 2).Value = House
        .Cells(r, 3).Value = Name
        .Cells(r, 4).Value = Address
        .Cells(r, 5).Value = Phone
        .Cells(r, 6).Value = Fax
        .Cells(r, 7).Value = Email
        .Cells(r, 8).Value = Total
        .Cells(r, 9).Value = Deposit
        .Cells(r, 10).Value = Balance
        .Cells(r, 11).Value = STax
        .Cells(r, 12).Value = CTax
        .Cells(r, 13).Value = TTax
        .Cells(r, 14).Value = Rent
        .Cells(r, 15).Value = Pet
        .Cells(r, 16).Value = Cleaning
        .Cells(r, 17).Value = HotTub
        .Cells(r, 18).Value = CheckIN
        .Cells(r, 19).Value = CheckOUT
        .Cells(r, 20).Value = NIGHTS
        .Cells(r, 21).Value = Origin
        .Cells(r, 22).Value = Lead
    End With

NOTE: You'll need to do the same thing with your header assignments, too.

Upvotes: 1

Related Questions