Data Collation Macro BUG

AnilPullagura

Board Regular
Joined
Nov 19, 2010
Messages
98
Hello All,

I have written a macro to collate data from numerous workbooks to a single one. This works well for the 1st workbook and from the second workbook, i noticed a weird thing.

The last row of data retrieved from 1st workbook is being stored in the variable and when the next workbook data is stored the Data Collation workbook, it populates the rowdata from 1st workbook for each and every row.

Here is the raw macro: Please suggest if I can improvise on this and fix the bug

Code:
  Public objFSO       As Object
    Public objFolder    As Object
    Public FileName     As Object
    Public i            As Long
    Public k()
Sub ListFiles()
 
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
 
    Dim StartFolder
            Set objFSO = CreateObject("Scripting.FileSystemObject")
            StartFolder = "C:\Documents and Settings\apullagura\Desktop\Dashboard July 2011"
            Set objFolder = objFSO.GetFolder(StartFolder)
 
    SubFoldersFiles objFSO.GetFolder(StartFolder)
        Dim wb As Workbook, wbCur As Workbook
        Dim pName       As String
        'Dim shname      As String
        Dim arrOutput()
        Dim opCols(1 To 6) As Long
        Dim ColHeads, j As Long, n As Long, c As Long
        'Dim wbOpen As Boolean: wbOpen = False
            Set wbCur = Workbooks("Data Collation.xls")
        ReDim arrOutput(1 To 1000, 1 To 10)
            ColHeads = Array("EmpName", "ProcessName", "ProdTarget", "Production", "Date", "ProductiveHours")
            With wbCur.Worksheets("OpsProdData") '<<==adjust to suit
                    Range("A2:F65536").Clear
                On Error Resume Next
                For j = 0 To UBound(ColHeads)
                    opCols(j + 1) = Cells.Find(What:=CStr(ColHeads(j)), LookAt:=xlPart).Column
                Next
            End With
        For i = 1 To UBound(k)
        Dim wbOpen As Boolean: wbOpen = False
            For Each wb In Application.Workbooks
                If wb.Name = k(i) Then
                    wbOpen = True
                    wb.Activate
                End If
            Next
                If wbOpen = False Then
                    Set wb = Workbooks.Open(k(i), 0)
                End If
        n = n + 1
'DATA TRANSFERRED TO VARIABLES
        With wb.Worksheets("Daily Production")
 
            inpt_col = Cells.Find(What:="S.No.", LookAt:=xlPart, MatchCase:=False).Offset(0, 1).Column
            inpt_lst_rw = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).End(xlDown).Offset(-1, 0).Row
            s = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(1, 0).Value
            If s = 1 Then
            inpt_fst_rw = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(1, 0).Row
            Else
            inpt_fst_rw = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(2, 0).Row
            End If
            'MsgBox inpt_lst_rw
            'MsgBox inpt_fst_rw
 
        For m = inpt_fst_rw To inpt_lst_rw
                arrOutput(n, 1) = .Cells(m, inpt_col).Value
                b = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(0, 2).Value
 
                    If b <> "" Then
                        inpt_q_lst_col = Cells.Find(What:="Total", LookAt:=xlWhole, MatchCase:=True).Offset(0, -1).Column
                        inpt_q_fst_col = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(0, 2).Column
                    Else
                        inpt_q_lst_col = Cells.Find(What:="Total", LookAt:=xlWhole, MatchCase:=False).Offset(0, -1).Column
                        inpt_q_fst_col = Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=False).Offset(0, 3).Column
                    End If
 
            For c = inpt_q_fst_col To inpt_q_lst_col
                    arrOutput(n, 2) = .Cells(3, c).Value
                    arrOutput(n, 3) = .Cells(3, c).Offset(1, 0).Value
                    arrOutput(n, 4) = .Cells(m, c).Value
                    arrOutput(n, 5) = Left((Now() - 1), 8)
                        g = Cells.Find(What:="Productive Hours", LookAt:=xlWhole, MatchCase:=False).Column
                    arrOutput(n, 6) = .Cells(m, g).Value
 
                    'If arrOutput(n, 2) <> "" Then GoTo Line1 Else GoTo Line2:
'Line1:
                    If n Then
                        wbCur.Activate
                    With wbCur.Worksheets("OpsProdData")
                        e = Cells(2, 1).Value
                            If e <> "" Then
                                f = Range("A65536").End(xlUp).Offset(1, 0).Row
                                .Range("a" & f).Resize(n, 6).Value = arrOutput
                            Else
                                .Range("A2").Resize(n, 6).Value = arrOutput
                            End If
                    End With
                End If
 
            Next c
'Line2:
            Next m
 
        End With
 
        wb.Close
 
 
Next
 
 
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
 
    'Msg = MsgBox("Report is Generated", vbOKOnly, "SUMMARY REPORT")
 
    Erase k
i = Empty
End Sub
Sub SubFoldersFiles(Folder)
Dim objfilename As String
objfilename = "Dash"
    For Each SubFolder In Folder.SubFolders
        Set objFolder = objFSO.GetFolder(SubFolder.Path)
        For Each FileName In objFolder.Files
            If FileName.Name Like "*" & objfilename & "*" Then
                i = i + 1
                ReDim Preserve k(1 To i)
                k(i) = objFolder & "\" & FileName.Name
            End If
        Next
        SubFoldersFiles SubFolder
    Next
End Sub
 

Excel Facts

What is the fastest way to copy a formula?
If A2:A50000 contain data. Enter a formula in B2. Select B2. Double-click the Fill Handle and Excel will shoot the formula down to B50000.
You could at least wait more than 20 minutes before bumping!

You have various With statements holding references to worksheets but none of the cells references within those blocks are actually qualified - they should all be .Cells rather than just Cells
I've only had a quick look so that may not be the cause of the issue you mention, but you ought to change it anyway!
 
Upvote 0
Thanks RORY & my sincere apology for a quick BUMP!!!

As you might have seen from the macro that, I am not an expert in VBA and can manage to get things done for my immediate needs.

So that .Cells stuff dint get thru my mind :(

However, i feel that the problem might be that the variable arrOutput is carry the last value from each workbook on the next work book

Suppose, if my last dataset retrieved from 1st workbook is:

Anil XYZ 250 200 07/06/2011 7.2

This above dataset is carried for every new dataset of 2nd work book as show below:

The 1st dataset from 2nd WB is populated as

Anil XYZ 250 200 07/06/2011 7.2
Suresh ABC 150 125 07/06/2011 8.0


Instead of
Suresh ABC 150 125 07/06/2011 8.0

Hope am much clear with this.

I was unable to identify why this is Happening. Any help on this is much appreciated.

Thanks,
Anil
 
Upvote 0
Here's a specific example:
Rich (BB code):
'DATA TRANSFERRED TO VARIABLES
        With wb.Worksheets("Daily Production")
 
            inpt_col = Cells.Find(What:="S.No.", LookAt:=xlPart, MatchCase:=False).Offset(0, 1).Column

the Cells property is in no way related back to your 'Daily Production' worksheet - it simply refers to whichever sheet is active. It should be:
Rich (BB code):
'DATA TRANSFERRED TO VARIABLES
        With wb.Worksheets("Daily Production")
 
            inpt_col = .Cells.Find(What:="S.No.", LookAt:=xlPart, MatchCase:=False).Offset(0, 1).Column

Note the dot in front of Cells. This applies to all your Cells references inside the With ... End With blocks.
 
Upvote 0
That was quick and self explanatory Rory. Thanks for that!!!

Does this fix the bug? I tried but it wasn't fruitful. Any views on the bug fix.

Thanks,
Anil
 
Upvote 0
This bit:
Rich (BB code):
            For Each wb In Application.Workbooks
                If wb.Name = k(i) Then
                    wbOpen = True
                    wb.Activate
                End If
            Next
should be:
Rich (BB code):
            For Each wb In Application.Workbooks
                If wb.Name = k(i) Then
                    wbOpen = True
                    wb.Activate
                    Exit For
                End If
            Next

If that still doesn't help then please post the revised code you are testing.
 
Upvote 0
Thanks Rory for the response, but apparently this did not do anything to fix the bug. Below is the present code that I am testing. Please rectify if there is any correction in the code to fix the bug.

Or

If you can provide me a much comprehensive code, I would be more than happy. I somehow feel that my code is not Optimized. Please give your valuable feedback. It will help me in learning a lot. Thanks once Again

Code:
  Public objFSO       As Object
    Public objFolder    As Object
    Public FileName     As Object
    Public i            As Long
    Public k()
Sub ListFiles()
 
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
 
    Dim StartFolder
            Set objFSO = CreateObject("Scripting.FileSystemObject")
            StartFolder = "C:\Documents and Settings\apullagura\Desktop\Dashboard July 2011"
            Set objFolder = objFSO.GetFolder(StartFolder)
 
    SubFoldersFiles objFSO.GetFolder(StartFolder)
        Dim wb As Workbook, wbCur As Workbook
        Dim pName       As String
        'Dim shname      As String
        Dim arrOutput()
        Dim opCols(1 To 6) As Long
        Dim ColHeads, j As Long, n As Long, c As Long
        'Dim wbOpen As Boolean: wbOpen = False
            Set wbCur = Workbooks("Data Collation.xls")
        ReDim arrOutput(1 To 1000, 1 To 10)
            ColHeads = Array("EmpName", "ProcessName", "ProdTarget", "Production", "Date", "ProductiveHours")
            With wbCur.Worksheets("OpsProdData") '<<==adjust to suit
                    Range("A2:F65536").Clear
                On Error Resume Next
                For j = 0 To UBound(ColHeads)
                    opCols(j + 1) = Cells.Find(What:=CStr(ColHeads(j)), LookAt:=xlPart).Column
                Next
            End With
        For i = 1 To UBound(k)
        Dim wbOpen As Boolean: wbOpen = False
            For Each wb In Application.Workbooks
                If wb.Name = k(i) Then
                    wbOpen = True
                    wb.Activate
                    Exit For
                End If
            Next
                If wbOpen = False Then
                    Set wb = Workbooks.Open(k(i), 0)
                End If
        n = n + 1
'DATA TRANSFERRED TO VARIABLES
        With wb.Worksheets("Daily Production")
 
            inpt_col = .Cells.Find(What:="S.No.", LookAt:=xlPart, MatchCase:=False).Offset(0, 1).Column
            inpt_lst_rw = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).End(xlDown).Offset(-1, 0).Row
            s = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(1, 0).Value
            If s = 1 Then
            inpt_fst_rw = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(1, 0).Row
            Else
            inpt_fst_rw = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(2, 0).Row
            End If
            'MsgBox inpt_lst_rw
            'MsgBox inpt_fst_rw
 
        For m = inpt_fst_rw To inpt_lst_rw
                arrOutput(n, 1) = .Cells(m, inpt_col).Value
                b = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(0, 2).Value
 
                    If b <> "" Then
                        inpt_q_lst_col = .Cells.Find(What:="Total", LookAt:=xlWhole, MatchCase:=True).Offset(0, -1).Column
                        inpt_q_fst_col = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=True).Offset(0, 2).Column
                    Else
                        inpt_q_lst_col = .Cells.Find(What:="Total", LookAt:=xlWhole, MatchCase:=False).Offset(0, -1).Column
                        inpt_q_fst_col = .Cells.Find(What:="S.No.", LookAt:=xlWhole, MatchCase:=False).Offset(0, 3).Column
                    End If
 
            For c = inpt_q_fst_col To inpt_q_lst_col
                    arrOutput(n, 2) = .Cells(3, c).Value
                    arrOutput(n, 3) = .Cells(3, c).Offset(1, 0).Value
                    arrOutput(n, 4) = .Cells(m, c).Value
                    arrOutput(n, 5) = Left((Now() - 1), 8)
                        g = Cells.Find(What:="Productive Hours", LookAt:=xlWhole, MatchCase:=False).Column
                    arrOutput(n, 6) = .Cells(m, g).Value
 
                    'If arrOutput(n, 2) <> "" Then GoTo Line1 Else GoTo Line2:
'Line1:
                    If n Then
                        wbCur.Activate
                    With wbCur.Worksheets("OpsProdData")
                        e = Cells(2, 1).Value
                            If e <> "" Then
                                f = Range("A65536").End(xlUp).Offset(1, 0).Row
                                .Range("a" & f).Resize(n, 6).Value = arrOutput
                            Else
                                .Range("A2").Resize(n, 6).Value = arrOutput
                            End If
 
                    End With
                End If
 
            Next c
'Line2:
            Next m
 
        End With
        arrOutput = Empty
        wb.Close
 
 
Next
 
 
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
 
    'Msg = MsgBox("Report is Generated", vbOKOnly, "SUMMARY REPORT")
 
    Erase k
i = Empty
End Sub
Sub SubFoldersFiles(Folder)
Dim objfilename As String
objfilename = "Dash"
    For Each SubFolder In Folder.SubFolders
        Set objFolder = objFSO.GetFolder(SubFolder.Path)
        For Each FileName In objFolder.Files
            If FileName.Name Like "*" & objfilename & "*" Then
                i = i + 1
                ReDim Preserve k(1 To i)
                k(i) = objFolder & "\" & FileName.Name
            End If
        Next
        SubFoldersFiles SubFolder
    Next
End Sub
 
Upvote 0
Comment out the On Error Resume Next line and run it again and tell us what happens. Incidentally, I notice that this check:
Code:
                If wb.Name = k(i) Then
will never work since k() contains the full file paths. You need:
Code:
                If wb.FullName = k(i) Then
 
Upvote 0
Code:
  With wbCur.Worksheets("OpsProdData") '<<==adjust to suit
    Range("A2:F65536").Clear
    On Error Resume Next
    For j = 0 To UBound(ColHeads)
      opCols(j + 1) = Cells.Find(What:=CStr(ColHeads(j)), LookAt:=xlPart).Column
    Next
  End With
To reiterate Rorya's first suggestion, you set up a With block but then you don't reference the With object in the code inside that block. In the above example you're using Range and Cells but these will refer to the active workbook and worksheet and not the With object wbCur.Worksheets("OpsProdData"). To do that you would have to prefix the words Range and Cells with a dot (period) as follows:-
Code:
  With wbCur.Worksheets("OpsProdData") '<<==adjust to suit
    [SIZE=3][COLOR=red][B].[/B][/COLOR][/SIZE]Range("A2:F65536").Clear
    On Error Resume Next
    For j = 0 To UBound(ColHeads)
      opCols(j + 1) = [B][COLOR=#ff0000].[/COLOR][/B]Cells.Find(What:=CStr(ColHeads(j)), LookAt:=xlPart).Column
    Next
  End With
The dots (period) are saying to VBA: prefix this with the name of the With object.

With doesn't mean: everything which follows should be prefixed with the name of this object.

Am I explaining this clearly?
 
Upvote 0

Forum statistics

Threads
1,224,504
Messages
6,179,142
Members
452,892
Latest member
JUSTOUTOFMYREACH

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top