Loop through folders - copy data from files to main file - vba

I want to do loop through folders and subfolders.
It works in my code. My next step is doing check - if specified cell in 4th column is not empty(in every file in subfolders), then copy values from files to my main file(for example ActiveWorkbook.ActiveSheet) - append.
In every try i have problems, now it is "Object variable or With block variables not set." But doing set makes new error.
Can someone help?
Regards
Sub DoFolder()
Dim fso, oFolder, oSubfolder, oFile, queue As Collection
Dim FileName As String
Dim PathName As String
Dim Wb As Workbook
Dim newbook As Worksheet
Dim i As Integer
Dim lastRow As Long
Dim col As Range, coll As Range
Dim someRange As Range
Set fso = CreateObject("Scripting.FileSystemObject")
Set queue = New Collection
queue.Add fso.GetFolder("Y:\MDM\__ZADANIA\LISTOWANIE\Archiwum\") 'obviously replace
Application.ScreenUpdating = False
'Nagłówki do nowego pliku z danymi
Set newbook = ActiveWorkbook.ActiveSheet
With newbook
.Columns("A").Cells(1, 1) = "Subsystem"
.Columns("B").Cells(1, 1) = "MGB"
.Columns("C").Cells(1, 1) = "EAN Zakupowy"
.Columns("D").Cells(1, 1) = "Liczba jednostek sprzedaży w kartonie"
.Columns("E").Cells(1, 1) = "Ilość sztuk w jednostce sprzedaży"
.Columns("F").Cells(1, 1) = "Nazwa pliku"
.Columns("G").Cells(1, 1) = "Katalog pliku"
End With
'Fitowanie kolumn
With newbook.Columns("A:G")
.AutoFit
End With
'zczytywanie ifnormacji z formatek po foldrach i dodawanie do istniejącego pliku
Do While queue.Count > 0
Set oFolder = queue(1)
queue.Remove 1
For Each oSubfolder In oFolder.SubFolders
queue.Add oSubfolder
Next oSubfolder
For Each oFile In oFolder.Files
Set Wb = Nothing
Set Wb = Workbooks.Open(oFile)
Wb.Windows(1).Visible = False
For i = 15 To 515
Set someRange = newbook.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
If Not someRange Is Nothing Then
lastRow = someRange.Row
Else
lastRow = 1
End If
If Wb.Sheets("Dane_Dostawcy").Cells(i, 4) <> "" Then
newbook.Cells(lastRow + 1, 1).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 4).Value
newbook.Cells(lastRow + 1, 2).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 4).Value
newbook.Cells(lastRow + 1, 3).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 30).Value
newbook.Cells(lastRow + 1, 4).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 56).Value
newbook.Cells(lastRow + 1, 5).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 14).Value
newbook.Cells(lastRow + 1, 6).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 4).Value
newbook.Cells(lastRow + 1, 7).Value = Wb.Sheets("Dane_Dostawcy").Cells(i, 4).Value
Else
GoTo MyStatement
End If
MyStatement:
Next i
Next oFile
Loop
Application.ScreenUpdating = True
End Sub

It is producing an error because it cannot find anything, and you are asking for the .Row of that anything.
This is a way to go around it:
Dim someRange As Range
Set someRange = newbook.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious)
If Not someRange Is Nothing Then
lastRow = someRange.Row
Else
lastRow = 1
End If
Thus it only gives the row value to lastRow in case that it has found something. Based on your business logic, if it does not find anything the row could be the first one.
Second Option for the error (thanks #QHarr) - you have to declare dim lastRow as Long and not as a range.

Related

Setting a range variable using another range variable

I'm having a bit of trouble with this and I'm not sure why...
My code (such that it is, a work in progress) is getting stuck on this line:
Set starRange = .Range(Cells(title), Cells(LR, 3))
Can I not use a range variable to set a new range in this way?
Sub cellPainter()
Dim ws As Worksheet
Dim starRange, titleRange, found As Range
Dim errorList() As String
Dim i, LR As Integer
i = 0
ReDim errorList(i)
errorList(i) = ""
For Each ws In ActiveWorkbook.Worksheets
With ws
LR = .Cells(.Rows.Count, "C").End(xlUp).Row
Set titleRange = .Range("C4")
If InStr(1, titleRange, "Title", vbBinaryCompare) < 1 Then
Set found = .Range("C:C").Find("Title", LookIn:=xlValues)
If Not found Is Nothing Then
titleRange = found
Else
errorList(i) = ws.Name
i = i + 1
ReDim Preserve errorList(i)
End If
End If
Set starRange = .Range(Cells(titleRange), Cells(LR, 3))
For Each cell In starRange
If InStr(1, cell, "*", vbTextCompare) > 0 Then Range(cell, cell.Offset(0, 2)).Interior.ColorIndex = 40
If InStr(1, cell, "*", vbTextCompare) = 0 Then Range(cell, cell.Offset(0, 2)).Interior.ColorIndex = 0
Next cell
End With
Next ws
If errorList(0) <> "" Then
txt = MsgBox("The following worksheets were missing the Title row, and no colour changes could be made:" & vbNewLine)
For j = 0 To i
txt = txt & vbCrLf & errorList(j)
Next j
MsgBox txt
End If
End Sub
Edit:
Rory cracked it!
When using a variable inside Range, the Cells property is not required:
Set starRange = .Range(titleRange, .Cells(LR, 3))

VBA Error: Runtime Error: 9 - Subscript out of range when copying a worksheet from another workbook

I am generating a new workbook from a multiple workbooks, i can generate a summary of all the errors found, but when i try to copy the sheets with the error information i got the runtime error 9
These is the line failing
If exists = True Then
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
Other thing i havent add is that all the sheets on the multiple files have the same names, so i want to know if there is a way that the sheet when is copy i can add the file name and the sheet name
Sub getViolations()
Path = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
Filename = Dir(Path & "*.xls")
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Set TxtRng = ws.Range("A1:N1")
TxtRng.Font.ColorIndex = 2
TxtRng.Interior.ColorIndex = 5
TxtRng.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
TxtRng.HorizontalAlignment = xlCenter
Dim i As Integer
i = 2
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
Dim wc As Worksheet
Set wc = ActiveWorkbook.Sheets("Violations Summary")
ws.Cells(i, 1).Value = ActiveWorkbook.Sheets("Violations Summary").Range("B1")
ws.Cells(i, 2).Value = ActiveWorkbook.Sheets("Violations Summary").Range("C1")
Dim count As Integer
count = 15
Dim sheetName As String, mySheetNameTest As String
Dim n As Integer
Dim exits As Boolean
For n = 3 To 14
If Not IsEmpty(wc.Cells(n, 2)) Then
If (wc.Cells(n, 2)) = 0 Then
ws.Cells(i, n).Font.ColorIndex = 4
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) > 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
exists = sheetExists(sheetName)
If exists = True Then
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
ws.Cells(i, count) = wc.Cells(1, n).Value
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (ActiveWorkbook.Sheets("Violations Summary").Cells(n, 2)) < 0 Then
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
End If
If IsEmpty(wc.Cells(n, 2)) Then
ws.Cells(i, n).Value = ["NA"]
End If
count = count + 1
Next n
Workbooks(Filename).Close
Filename = Dir()
i = i + 1
Loop
End Sub
Function sheetExists(sheetToFind As String) As Boolean
sheetExists = False
For Each Sheet In Worksheets
If sheetToFind = Sheet.Name Then
sheetExists = True
Exit Function
End If
Next Sheet
End Function
Put option explicit at top so spelling of variables is checked and that they are declared. The variable exists was mispelt and there were a number of other variables not declared. I have put some other comments in with the code.
Some of the logic i think can be simplified and i have given some examples. Also, ensure consistent use of named variable wc. If nothing else it should be easier to debug now. Compiles on my machine so give it a try.
This all works on the assumption that each workbook you open has the "Violations Summary" sheet and it is spelt as shown.
You have the filename already stored in the variable Filename so you can use (concatenate?) that with the sheetname variable.
Option Explicit 'Set this to ensure all variable declared and consistent spelling
'Consider using WorkSheets collection rather than Sheets unless you have chart sheets as well?
Sub getViolations()
Dim Path As String 'Declare you other variables
Dim FileName As String
Path = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
FileName = Dir(Path & "*.xls")
Dim ws As Worksheet
Dim TxtRng As Range 'Declare this
Set ws = ThisWorkbook.Sheets("Sheet1")
Set TxtRng = ws.Range("A1:N1")
TxtRng.Font.ColorIndex = 2
TxtRng.Interior.ColorIndex = 5
TxtRng.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
TxtRng.HorizontalAlignment = xlCenter
Dim i As Integer
i = 2
Do While FileName <> ""
Workbooks.Open FileName:=Path & FileName, ReadOnly:=True
Dim wc As Worksheet 'Consider whether to place these declarations just before the loop, avoids risk others may think there will be reinitialization even though there isn't
Set wc = ActiveWorkbook.Sheets("Violations Summary")
ws.Cells(i, 1).Value = wc.Range("B1") 'Use the wc variable
ws.Cells(i, 2).Value = wc.Range("C1")
Dim count As Integer
Dim sheetName As String, mySheetNameTest As String
Dim n As Integer
Dim exists As Boolean 'Corrected spelling
count = 15
For n = 3 To 14
If Not IsEmpty(wc.Cells(n, 2)) Then
If (wc.Cells(n, 2)) = 0 Then
ws.Cells(i, n).Font.ColorIndex = 4
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) > 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
exists = sheetExists(sheetName)
If exists Then 'Shortened by removing = True (evaluates in same way)
ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1)
End If
ws.Cells(i, count) = wc.Cells(1, n).Value
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
If (wc.Cells(n, 2)) < 0 Then 'used wc variable
ws.Cells(i, n).Font.ColorIndex = 3
ws.Cells(i, n).Value = wc.Cells(n, 2)
End If
Else 'Simplified this as if is not empty then is empty so can use else
ws.Cells(i, n).Value = ["NA"] 'what is pupose of square brackets? These can be removed i think
End If
count = count + 1
Next n
Workbooks(FileName).Close
FileName = Dir()
i = i + 1
Loop
End Sub
Function sheetExists(sheetToFind As String) As Boolean
Dim Sheet As Worksheet ' declare
sheetExists = False
For Each Sheet In Worksheets
If sheetToFind = Sheet.Name Then
sheetExists = True
Exit Function
End If
Next Sheet
End Function
After you copy the ActiveWorkbook.Sheets(sheetName) to ThisWorkbook, ThisWorkbook becomes the ActiveWorkbook. ActiveWorkbook.Sheets(sheetName).Copy After:=ThisWorkbook.Sheets(1) should not throw an error but will probably cause ActiveWorkbook.Sheets("Violations Summary") to fail. For this reason, you should always fully qualify your references.
Some idealist programmers say that a subroutine should perform 1 simply task. Personally, I believe that if you have to scroll up, down, left or right to see what your code is doing it is time to refactor it. When refactoring I try to extract logical groups of tasks in a separate subroutine. This makes debugging and modifying the code far easier.
Refactored Code
Option Explicit
Sub getViolations()
Const Path As String = "C:\Users\omartinr\Desktop\New folder (4)\New folder\"
Dim n As Long
Dim Filename As String
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
Sheet1Setup ws
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
ProcessWorkbook Filename, ws.Rows(n)
Filename = Dir()
Loop
End Sub
Sub ProcessWorkbook(WBName As String, row As Range)
Dim nOffset As Long, n As Long
Dim sheetName As String
Dim WB As Workbook
Set WB = Workbooks.Open(Filename:=Path & Filename, ReadOnly:=True)
With WB.Sheets("Violations Summary")
row.Columns(1).Value = .Range("B1")
row.Columns(2).Value = .Range("C1")
nOffset = 12
For n = 3 To 14
If .Cells(n, 2) = "" Then
row.Columns(n).Value = ["NA"]
ElseIf (.Cells(n, 2)) = 0 Then
row.Columns(n).Font.ColorIndex = 4
row.Columns(n).Font.ColorIndex = 0
ElseIf (.Cells(n, 2)) = 0 Then
Select Case wc.Cells(n, 1)
Case "PK"
sheetName = "Peak"
Case "Sfactor"
sheetName = "SF Supply"
Case Else
sheetName = wc.Cells(n, 1)
End Select
'Range.Parent refers to the ranges worksheet. row.Parent refers to ThisWorkbook.Sheets(1)
If SheetExists(WB, sheetName) Then .Copy After:=row.Parent.Sheets(1)
row.Columns(n + nOffset) = .Cells(1, n).Value
row.Columns(n).Font.ColorIndex = 3
row.Columns(n).Value = .Cells(n, 2)
End If
Next
End With
WB.Close SaveChanges:=False
End Sub
Function SheetExists(WB As Workbook, sheetToFind As String) As Boolean
Dim ws As Worksheet
For Each ws In WB.Worksheets
If sheetToFind = ws.Name Then
SheetExists = True
Exit Function
End If
Next
End Function
Sub Sheet1Setup(ws As Worksheet)
With ws.Range("A1:N1")
.Value = [{"Partition Name","Tag","EM Supply","SH Signal","PK","Sfactor","FiSH","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL","RESCAL"}]
.Font.ColorIndex = 2
.Interior.ColorIndex = 5
.HorizontalAlignment = xlCenter
End With
End Sub
Note: row is the target Row of ThisWorkbook.Sheets(1). row.Columns(3) is a fancy way to write row.Cells(1, 3) which refers to the 3rd cell in the target row. Also note that Cells, Columns, and Rows are all relative to the range they belong to. e.g. Range("C1").Columns(2) refers to D1, Range("C1").Rows(2).Columns(2) refers to D2, Range("C1").Cells(2,2) also refers to D2.

Loop that returns to starting point for selecting Nth row

I want to select M companies from a sample of S companies and doing this starting from a random number selected between 1 and S and selecting every Nth company.
To get the sample of M, I want the loop to come back to starting point for selecting the companies. Here xInterval is N, lrowCount is S and M is N/S. I tried using offset and changing indices of for loop.
Can anyone suggest a solution?
Sub circularSystematicSampling()
Dim rng As Range
Dim InputRng As Range
Dim OutRng As Range
Dim xInterval As Integer
Dim lrowCount As Integer
Dim endPoint As Integer
Dim circular As Boolean
xTitleId = "Testing"
Set InputRng = ActiveSheet.UsedRange
Set InputRng = InputRng.Offset(1).Resize(InputRng.Rows.Count - 1)
InputRng.Select
xInterval = Application.InputBox("Number of companies is" & " " & InputRng.Rows.Count & vbCrLf & " Enter row interval", xTitleId, Type:=1)
lrowCount = ActiveSheet.UsedRange.Rows.Count
randomStart = Int((lrowCount - 1 + 1) * Rnd + 1)
endPoint = Int(lrowCount + randomStart)
endPoint2 = Int(randomStart - 1)
If endPoint > lrowCount Then
circular = True
End If
For i = (1 + randomStart) To endPoint Step xInterval
Set rng = InputRng.Cells(i, 1)
If circular Then
ActiveCell.Offset(1, 0).Select
End If
If OutRng Is Nothing Then
Set OutRng = rng
Else
Set OutRng = Application.Union(OutRng, rng)
End If
Next
OutRng.EntireRow.Select
With Selection.Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub
How do I modify this loop to come back to starting point when selecting xInterval row? Thanks.
Edit: Another approach while circular true
If circular Then
For j = 1 To endPoint2 Step xInterval ' ActiveCell.Offset(1, 0).Select
Set rng2 = InputRng.Cells(j, endPoint2)
End If
If OutRng Is Nothing Then
Set OutRng = rng
Else
Set OutRng = Application.Union(OutRng, rng, rng2)
End If
Another possibility using DO while
For i = (1 + randomStart) To endPoint Step xInterval
Do While Not IsEmpty(ActiveCell)
Set rng = InputRng.Cells(i, endPoint)
Do While IsEmpty(ActiveCell)
ActiveCell.Offset(1, 0).Select
For j = 1 To endPoint2 Step xInterval
Set rng2 = InputRng.Cells(j, endPoint2)
End If
If OutRng Is Nothing Then
Set OutRng = rng
Else
Set OutRng = Application.Union(OutRng, rng, rng2)
End If
If you just loop over the actual rows from 1 to S then you can use the Mod function to send the loop back 'to the top':
For lngCounter = 1 To lngRowCount Step lngRowInterval
lngTargetRow = (lngRandRowStart + lngCounter) Mod lngRowCount
strOutRanges = strOutRanges & rngData.Cells(lngTargetRow + 1, 1).Address & ","
Next lngCounter
I had an issue with your method of Unioning the Ranges so am just building a list of cell addresses to format in the loop.
Full example:
Option Explicit
Sub circularSystematicSampling()
Dim rngData As Range
Dim lngRowCount As Long
Dim lngRowInterval As Long
Dim lngRandRowStart As Long
Dim lngCounter As Long
Dim lngTargetRow As Long
Dim strOutRanges As String
Dim rngOut As Range
' set range to iterate
Set rngData = ThisWorkbook.Worksheets("Sheet1").UsedRange
' drop header
Set rngData = rngData.Offset(1).Resize(rngData.Rows.Count - 1)
' get total rows
lngRowCount = rngData.Rows.Count
' set an interval
lngRowInterval = Application.InputBox("Enter row interval", "Test", 1)
' set a random start point
lngRandRowStart = Int(rngData.Rows.Count * Rnd + 1)
' iterate rows - calculate offset in loop
strOutRanges = ""
For lngCounter = 1 To lngRowCount Step lngRowInterval
lngTargetRow = (lngRandRowStart + lngCounter) Mod lngRowCount
strOutRanges = strOutRanges & rngData.Cells(lngTargetRow + 1, 1).Address & ","
Next lngCounter
'drop trailing comma
strOutRanges = Left(strOutRanges, Len(strOutRanges) - 1)
' create range with string of addresses
Set rngOut = Range(strOutRanges)
Debug.Print rngOut.Address
With rngOut.EntireRow.Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End Sub

how to change output location for each loop and run multiple loops

I have code here which loops through a list of files; opening them, extracting data and moving it into the main workbook. What i am looking to do get it so the data for abel is in columns c and d but then put varo in f and g etc. the problem that i see is that the placement code is inside the loop so for each i it will just write over the previous line instead of being in a different column all together!
Sub Source_Data()
Dim r
Dim findValues() As String
Dim Wrbk As Workbook
Dim This As Workbook
Dim sht As Worksheet
Dim i
Dim tmp
Dim counter
Dim c As Range
Dim firstAddress
Dim rng As Range
ReDim findValues(1 To 3)
findValues(1) = "abel"
findValues(2) = "varo"
findValues(3) = "Tiger"
counter = 0
r = Range("A1").End(xlDown).Row
Set rng = Range(Cells(1, 1), Cells(r, 1))
Set This = ThisWorkbook
For Each tmp In rng
Workbooks.Open tmp
Set Wrbk = ActiveWorkbook
Set sht = ActiveSheet
For i = 1 To 3
With sht.Range(Cells(1, 1), Range("A1").SpecialCells(xlCellTypeLastCell))
Set c = .Find(findValues(i), LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Offset(0, 2).Value
Do
This.Activate
tmp.Offset(0, 2).Value = tmp.Value
tmp.Offset(0, 3).Value = firstAddress
Set c = .FindNext(c)
counter = counter + 1
Loop While Not c Is Nothing And c.Value = firstAddress
End If
End With
Wrbk.Activate
Next
Wrbk.Close
Next tmp
End Sub
**EDIT:**I know it can be done by adding a multiplier of "i" to the offset value but this makes things bigger than they need to be if i wish to search for 50 keywords
Here is my answer, hope to help you, and as always, if you need an improvement, just tell me.
Sub Source_Data()
Dim r
Dim findValues() As String
Dim Wrbk As Workbook
Dim This As Workbook
Dim sht As Worksheet
Dim i
Dim tmp
Dim counter
Dim c As Range
Dim firstAddress
Dim rng As Range
Dim ColNum 'the columns number var
ReDim findValues(1 To 3)
findValues(1) = "abel"
findValues(2) = "varo"
findValues(3) = "Tiger"
counter = 0
r = Range("A1").End(xlDown).Row
Set rng = Range(Cells(1, 1), Cells(r, 1))
Set This = ThisWorkbook
For Each tmp In rng
Workbooks.Open tmp
Set Wrbk = ActiveWorkbook
Set sht = ActiveSheet
For i = 1 To 3
With sht.Range(Cells(1, 1), Range("A1").SpecialCells(xlCellTypeLastCell))
Set c = .Find(findValues(i), LookIn:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Offset(0, 2).Value
Do
This.Activate
Select Case i 'Test var i (the value)
Case "abel" 'in case the value (that is a string) is equal to...
ColNum = 1 'set the var, with the number of the column you want
Case "varo" 'in case the value...
ColNum = 2 'Set the column...
Case "Tiger"
ColNum = 3
Case Else 'In case that the i var not match with anyvalue take this column number
ColNum = 20 'the garbage!
End Select
tmp.Offset(0, ColNum).Value = tmp.Value 'Put the value in the selected columns
tmp.Offset(0, ColNum + 1).Value = firstAddress 'and put the value to the next column of the
'selected column
Set c = .FindNext(c)
counter = counter + 1
Loop While Not c Is Nothing And c.Value = firstAddress
End If
End With
Wrbk.Activate
Next
Wrbk.Close
Next tmp
End Sub
Note:
You need to set the ColNum var to the values that you need, put there the numbers of the columns you really need to store the value of i and the next line is to put the address of the i var
You can just change these two lines:
tmp.Offset(0, 2).Value = tmp.Value
tmp.Offset(0, 3).Value = firstAddress
To this
tmp.Offset(0, 2 + (i-1)*2).Value = tmp.Value
tmp.Offset(0, 3 + (i-1)*2).Value = firstAddress

Read another file as input in vba

I have this macro in a excel file:
Sub ore()
Sheets(1).Select
LR = Cells(Rows.Count, "A").End(xlUp).Row
drow = 2
For r = 2 To LR
ore = Cells(r, 4)
nome = Cells(r, 2)
totore = totore + ore
n = n + 1
If ore <> 8 Then
Rows(r).Copy Sheets("log").Cells(drow, 1)
drow = drow + 1
End If
If n = 5 Then
' Stop
If totore <> 40 Then
Sheets("log").Cells(drow - 1, 5) = totore
End If
n = 0: totore = 0
End If
Next
Sheets("log").Select
End Sub
That starts when i click a button. This file is called "example.xlsm". I want take this macro and write it in another file called "readfile.xlsm" and call as an input to the "example.xlsm" file. So I need to read the data of "example.xlsm" file in summary. How can I do this? I tried to write
Workbooks.Open "C:\Users\Me\Desktop\example.xlsm"
but it doesn't work. Thanks
EDIT:
Sub Sample()
Dim path As String
Dim openWb As Workbook
Dim openWs As Worksheet
path = "C:\Users\Me\Desktop\example.xlsm"
Set openWb = Workbooks.Open(path)
Set openWs = openWb.Sheets("Sheet1")
With openWs
'~~> Rest of your code here
Sheets(1).Select
LR = Cells(Rows.Count, "A").End(xlUp).Row
drow = 2
For r = 2 To LR
ore = Cells(r, 4)
nome = Cells(r, 2)
totore = totore + ore
n = n + 1
If ore <> 8 Then
Rows(r).Copy Sheets("log").Cells(drow, 1)
drow = drow + 1
End If
If n = 5 Then
' Stop
If totore <> 40 Then
Sheets("log").Cells(drow - 1, 5) = totore
End If
n = 0: totore = 0
End If
Next
Sheets("log").Select
End With
'openWb.Close (True)
End Sub
This doesn't work either.
You need to create your object and then work with them. See this example. This code goes in readfile.xlsm
Sub Sample()
Dim path As String
Dim openWb As Workbook
Dim openWs As Worksheet
path = "C:\Users\Me\Desktop\example.xlsm"
Set openWb = Workbooks.Open(path)
Set openWs = openWb.Sheets("Sheet1")
With openWs
'~~> Rest of your code here
End With
'openWb.Close (True)
End Sub
FOLLOWUP (From Comments)
When I meant rest of the code, I didn't mean that you copy paste the original code and not make any changes to it :p Also another important tip: Use Option Explicit I see lot of undeclared variables. I have declared all of them to Long Change as applicable
Try this (Untested)
Option Explicit
Sub Sample()
Dim path As String
Dim openWb As Workbook, thiswb As Workbook
Dim openWs As Worksheet, Logws As Worksheet
Dim LR As Long, dRow As Long, r As Long, n As Long
Dim ore As Long, nome As Long, totore As Long
path = "C:\Users\Me\Desktop\example.xlsm"
Set thiswb = ThisWorkbook
Set openWb = Workbooks.Open(path)
Set openWs = openWb.Sheets("Sheet1")
Set Logws = openWb.Sheets.Add
'~~> Create Log Sheet
On Error Resume Next
Application.DisplayAlerts = False
openWb.Sheets("log").Delete
Application.DisplayAlerts = True
On Error GoTo 0
Logws.Name = "log"
With openWs
'~~> Rest of your code here
LR = .Cells(.Rows.Count, "A").End(xlUp).Row
dRow = 2
For r = 2 To LR
ore = .Cells(r, 4).Value
'nome = .Cells(r, 2).Value '<~~ Why do we need this?
totore = totore + ore
n = n + 1
If ore <> 8 Then
.Rows(r).Copy Logws.Cells(dRow, 1)
dRow = dRow + 1
End If
If n = 5 Then
If totore <> 40 Then
Logws.Cells(dRow - 1, 5) = totore
End If
n = 0: totore = 0
End If
Next
End With
'openWb.Close (True)
End Sub