Program Error Subscript out of Range ... Tried On Error Resume - vba

I am having problem with the subscript out of range with this line:
datasheet = wbook.Sheets("Month and Year")
I have tried to use On Error Resume but I might have done it wrong.
This code is suppose to establish month and year so that later, I am able to use it when I create a new sheet and refer to the previous one named similarly "Forecast Month Year". afterwards, it looks at 3 columns to validate that it is the row that it wants to copy and paste and then establishes it on the respective sheet.
Sub repeatingrows()
Dim wbook As Workbook
Set wbook = Application.ActiveWorkbook
'CHECKS THE MONTH TO INCREASE THE YEAR
Dim datasheet As Worksheet
datasheet = wbook.Sheets("Month and Year")
Dim m As Integer
Dim y As Integer
Dim t As Integer
For t = 2 To 13
For m = 1 To 13
If m = 13 Then
y = y + 1
m = 1
End If
Next m
m = .Cells(t, 1)
.Cells(t, 1) = .Cells(t, 2)
Next t
'MAKE NEW SHEET AND RENAME IT
Dim oldsheet As Worksheet
Dim newsheet As Worksheet
Set oldsheet = Application.ActiveSheet
oldsheet = Sheets("Forecast " & m & " " & y)
newsheet = Sheets("Forecast " & (m + 1) & " " & y)
Sheets.Add.Name = "Forecast " & (m + 1) & " " & y
'CHECK IF the 3 columns ARE SIMILAIR TO PREVIOUS PAGE
Dim rrow As Integer
For rrow = 3 To 500
If Sheets(3).Cell(rrow, 2) = Sheets(2).Cell(rrow, 2) Then
If Sheets(3).Cell(rrow, 5) = Sheets(2).Cell(rrow, 5) Then
If Sheets(3).Cell(rrow, 6) = Sheets(2).Cell(rrow, 6) Then
With newsheet
oldsheet.Range(oldsheet.Cells(rrow, 16), oldsheet.Cells(rrow, 19)).Copy
.Range(.Cells(b, a), .Cells(99, 51)).PasteSpecial xlPasteValues, xlPasteSpecialOperationAdd
End With '^COPY AND PASTES THE ROW
Else
End If
Else
End If
Else
End If
Next rrow
End Sub

try:
Set datasheet = wbook.Sheets("Month and Year")
and check the spelling of the sheetnameand check that the sheet exists in the proper workbook.and don't use .Cells() without a With
(there may be other errors)

Related

End(xlDown) for single rows

I have a macro that is working 99% of the time, but giving me trouble with one portion. I have data that is split into different size groups depending on certain parameters. The groups range from 1 row to as many at 10+. I am trying to copy each of the "groups" and paste into a template sheet and save which I've figured out.
Row Column B Column C
1 ASDF a
2 SDF a
3 WIRO a
4 VNDH a
5
6 FIJDK b
7 DFKIEL b
8
9 DLFKD c
10
11 OYPTK d
12 SSAODKJ d
13 SKJSJ d
Where I'm having trouble is Row 9 where Column b B = DLFKD and Column C = C
Desired Output:
Copy only row 9
Actual Output:
Copying Rows 9- 11
Existing Macro:
Data begins on Row 5.
Sub templatecopy()
Dim x As Workbook
Dim y As Workbook
Dim N As Long
Dim name As String
'## Open both workbooks first:
Set x = ActiveWorkbook
'Set R
R = 5
'start Loop
Do Until N = 96
Set y = Workbooks.Open("F:\Logistics Dashboard\Customs Macro\Cover Sheet Template.xlsx")
'set N
N = Range("B" & R).Cells(1, 1).End(xlDown).Row
'Now, copy Container Numbers from x and past to y(template):
x.Sheets("Sheet1").Range("B" & R & ":C" & N).Copy
y.Sheets("Sheet1").Range("A14").PasteSpecial
'save as Name of Vessel
name = "F:\Logistics Dashboard\Customs Macro\" & y.Sheets("Sheet1").Range("A14").Value & ".xlsx"
ActiveWorkbook.SaveAs Filename:=name
'Close template after saving to reset:
y.Close
'set R equal to new row to start
R = N + 2
Loop
End Sub
The issue is with how I am setting "N". Its having trouble distinguishing Row 9 where its just one row of data.
With the correct sheet selected this line of code should select the ranges on your sheet:
Thisworkbook.Worksheets("Sheet1").range("B:C").specialcells(xlcelltypeconstants,23).select
You'll need to add another line to account for formula as well as constants.
Public Sub FindRegionsOnSheet()
Dim sAddress As String
Dim aAddress() As String
Dim vItem As Variant
Dim x As Long
Dim wbTarget As Workbook
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Set wbTarget = Workbooks.Open("F:\Logistics Dashboard\Customs Macro\Cover Sheet Template.xlsx")
Set wsTarget = wbTarget.Worksheets("Sheet1")
'Find all ranges of constant & formula values in column B:C.
With wsSource.Columns(2).Resize(, 2)
On Error Resume Next
sAddress = .SpecialCells(xlCellTypeConstants, 23).Address(0, 0) & ","
sAddress = sAddress & .SpecialCells(xlCellTypeFormulas, 23).Address(0, 0)
If Right(sAddress, 1) = "," Then sAddress = Left(sAddress, Len(sAddress) - 1)
On Error GoTo 0
End With
'Place within an array.
If Not sAddress = vbNullString Then
If InStr(1, sAddress, ",") = 0 Then
ReDim aAddress(0 To 0)
aAddress(0) = "'" & wsSource.Name & "'!" & sAddress
Else
aAddress = Split(sAddress, ",")
For x = LBound(aAddress) To UBound(aAddress)
aAddress(x) = "'" & wsSource.Name & "'!" & aAddress(x)
Next x
End If
End If
''''''''''''''''''''''''''''''''''''''''
'Not sure how what you're doing once moved to the Target book......
'Think this is correct, but test first...
''''''''''''''''''''''''''''''''''''''''
For Each vItem In aAddress
wsTarget.Cells.Clear
Range(vItem).Copy Destination:=wsTarget.Range("A14")
wbTarget.SaveCopyAs "F:\Logistics Dashboard\Customs Macro\" & wbTarget.Sheets("Sheet1").Range("A14") & ".xlsx"
Next vItem
wbTarget.Close
End Sub
The 23 in the SpecialCells indicates what types of cells to include in the result:
XlSpecialCellsValue constants Value
xlErrors 16
xlLogical 4
xlNumbers 1
xlTextValues 2
These values can be added together to return more than one type (total = 23). The default is to select all constants or formulas, no matter what the type.... so probably don't need the 23 at all.

Set New opened workbook as wb give Application /object-defined error

The whole code works well until I set new opened workbook as wb and refer it to respected range. So suppose there is nothing wrong with my If and EndIf position.I tried several times with different way. With wb , ... Object-defined error. I remove .Value from Score, it gives error. using long range statement instead of Score, also give error. Where should I change? Thank you
Option Explicit
Sub TryFloo()
Dim year As String, x As String, startdate As String, month As String
Dim first As Integer, second As Integer, addDay As Integer, daterow As Integer
Dim mainbk As Workbook, wb As Workbook
Dim r&, i&, m As Integer
Dim path As String
Dim Score As Range
Set mainbk = Workbooks("kumpul mean.xlsm")
r = 5
With mainbk
If IsError(.Sheets(2).Range("E" & r)) Then '<---- Open first If()
Exit For
Else
year = ThisWorkbook.Sheets(2).Range("A" & r).Value
x = Range("C" & r).Value
addDay = Range("E" & r).Value - 1
first = InStr(x, "/")
second = InStr(first + 1, x, "/")
startdate = Mid(x, 1, 2)
month = Mid(x, first + 1, second - first - 1)
If month = 11 Then m = 1
If month = 12 Then m = 31
If month = 1 Then m = 62
End If
path = "E:\SouthNorth\1979.xls"
Set wb = Workbooks.Open(Filename:=path)
wb.Activate
daterow = m + startdate
For i = daterow To daterow + addDay
With wb
Score = .Sheets(1).Range(Cells(i, 24))'<--- Application/object-defined error
If Score.Value > 12 And Score.Value < 14 Then Worksheets("Sheet2").Range("C" & i).Value = 1
ElseIf Score.Value > 14 And Score.Value < 16 Then Worksheets("Sheet2").Range("C" & i).Value = 2
ElseIf Score.Value > 16 Then Worksheets("Sheet2").Range("C" & i).Value = 3
End If
End With
Next i
'wb.Close SaveChanges:=True '<- left open for checking
End If '<---- close first If()
End With
End Sub
wb.Range(Cells(i, 24)) is incorrect. The Cells is a property of a worksheet and not workbook.
Try something like this
wb.Sheets("Sheet1").Range("X" & i)
or
wb.Sheets("Sheet1").Cells(i,24)

Excel VBA Runtime Error 1004 while looping through sheets and extracting data

I'm writing an excel VBA script to loop through a set of 4 sheets, find a string at the top of a column of data, loop through all the data in that column and print the header and data in a summary tab.
I'm new to VBA and even after extensive research can't figure out why I'm getting Runtime error 1004 "Application-defined or object-defined error."
Here is the VBA code:
Private Sub CommandButton1_Click()
Dim HeaderList(1 To 4) As String, sheet As Worksheet, i As Integer, j As Integer, Summary As Worksheet
'Define headers to look for
HeaderList(1) = "Bananas"
HeaderList(2) = "Puppies"
HeaderList(3) = "Tigers"
'Loop through each sheet looking for the right header
For Each sheet In Workbooks("Tab Extraction Test.xlsm").Worksheets
i = i + 1
'Debug.Print i
'Debug.Print HeaderList(i)
Set h = Cells.Find(What:=HeaderList(i))
With Worksheets("Summary")
Worksheets("Summary").Cells(1, i).Value = h
End With
Col = h.Column
Debug.Print Col
Row = h.Row
Debug.Print Row
j = Row
'Until an empty cell in encountered copy the value to a summary tab
Do While IsEmpty(Cells(Col, j)) = False
j = j + 1
V = Range(Col, j).Value
Debug.Print V
Workbooks("Tab Extraction Test.xlsm").Worksheets("Summary").Cells(j, i).Value = V
Loop
Next sheet
End Sub
The error occurs at
Worksheets("Summary").Cells(1, i).Value = h
From other posts I thought this might be because I was trying to add something to a different cell than the one that was active in the current loop so I added a With statement but to no avail.
Thank you in advance for your help.
Following the comments above, try the code below.
Note: I think your Cells(Row, Col) is mixed-up, I haven't modified it yet in my answer below. I think Cells(Col, j) should be Cells(j, Col) , no ?
Code
Option Explicit
Private Sub CommandButton1_Click()
Dim HeaderList(1 To 4) As String, ws As Worksheet, i As Long, j As Long, Summary As Worksheet
Dim h As Range, Col As Long
'Define headers to look for
HeaderList(1) = "Bananas"
HeaderList(2) = "Puppies"
HeaderList(3) = "Tigers"
' set the "Summary" tab worksheet
Set Summary = Workbooks("Tab Extraction Test.xlsm").Worksheets("Summary")
'Loop through each sheet looking for the right header
For Each ws In Workbooks("Tab Extraction Test.xlsm").Worksheets
With ws
i = i + 1
Set h = .Cells.Find(What:=HeaderList(i))
If Not h Is Nothing Then ' successful find
Summary.Cells(1, i).Value = h.Value
j = h.Row
'Until an empty cell in encountered copy the value to "Summary" tab
' Do While Not IsEmpty(.Cells(h.Column, j))
Do While Not IsEmpty(.Cells(j, h.Column)) ' <-- should be
j = j + 1
Summary.Cells(j, i).Value = .Cells(j, h.Column).Value
Loop
Set h = Nothing ' reset range object
End If
End With
Next ws
End Sub
Try this one.
Private Sub CommandButton1_Click()
Dim HeaderList As Variant, ws As Worksheet, i As Integer, j As Integer, Summary As Worksheet
Dim lastRow As Long, lastCol As Long, colNum As Long
HeaderList = Array("Bananas", "Puppies", "Tigers", "Lions")
For Each ws In Workbooks("Tab Extraction Test.xlsm").Worksheets
lastCol = ws.Range("IV1").End(xlToLeft).Column
For k = 1 To lastCol
For i = 0 To 3
Set h = ws.Range(Chr(k + 64) & "1").Find(What:=HeaderList(i))
If Not h Is Nothing Then
lastRow = ws.Range(Chr(h.Column + 64) & "65536").End(xlUp).Row
colNum = colNum + 1
' The below line of code adds a header to summary page (row 1) showing which workbook and sheet the data came from
' If you want to use it then make sure you change the end of the follpowing line of code from "1" to "2"
' ThisWorkbook.Worksheets("Summary").Range(Chr(colNum + 64) & "1").Value = Left(ws.Parent.Name, Len(ws.Parent.Name) - 5) & ", " & ws.Name
ws.Range(Chr(h.Column + 64) & "1:" & Chr(h.Column + 64) & lastRow).Copy Destination:=ThisWorkbook.Worksheets("Summary").Range(Chr(colNum + 64) & "1")
Exit For
End If
Next i
Next k
Next ws
End Sub
Sometimes you have to remove blank sheets. Say you have 2k sheets because you combined a bunch of txt files into one workbook. But they're all in one column. So you loop through to do a text2columns. It does some of them but not all of them. It stops to give you run-time error 1004. Try removing blank sheets before looping through to do text2columns or something else.
Sub RemoveBlankSheets_ActiveWorkbook()
'PURPOSE: Delete any blanks sheets in the active workbook
'SOURCE: www.TheSpreadsheetGuru.com/the-code-vault
Dim sht As Worksheet
Application.ScreenUpdating = False
Application.DisplayAlerts = False
For Each sht In ActiveWorkbook.Worksheets
If WorksheetFunction.CountA(sht.Cells) = 0 And _
ActiveWorkbook.Sheets.Count > 1 Then sht.Delete
Next sht
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub

Evaluate and Store Complex Expression in Excel VBA

I am working on an accounting VBA program that will post Journal entries to a Ledger, and then generate trial balances (i.e. print out the values on a new sheet following "Bal. " in the Ledger). To do this, I need a way to assign the numerical part of the balance cells to a variable or collection. Unfortunately, when I use Debug.Print I see the only value stored is 0 (I am testing just with Common Stock). My expression is: y = Application.Evaluate("=SUM(R[-" & x & "]C:R[-1]C)-SUM(R[-" & x & "]C[1]:R[-1]C[1])") where y represents the balance of Common Stock. How do I properly store the balance value in a variable?
' TODO BE ABLE TO RUN MULTIPLE TIMES
' CHECK FOR POSTED MARK & START WRITING WHEN
' r = "one of the keys", or just creates new Ledger Worksheet every time
Sub MacCompileData()
Application.ScreenUpdating = False
Dim lastRow As Long, x As Long
Dim data, Key
Dim r As Range
Dim cLedger As Collection, cList As Collection
Set cLedger = New Collection
With Worksheets("Journal")
lastRow = .Range("B" & .Rows.Count).End(xlUp).Row
For x = 2 To lastRow
Key = Trim(.Cells(x, 2))
On Error Resume Next
Set cList = cLedger(Key)
If Err.Number <> 0 Then
Set cList = New Collection
cLedger.Add cList, Key
End If
On Error GoTo 0
cLedger(Key).Add Array(.Cells(x, 1).Value, .Cells(x, 3).Value, .Cells(x, 4).Value)
Worksheets("Journal").Cells(x, 5).Value = ChrW(&H2713)
Next
End With
With Worksheets("Ledger")
Dim IsLiability As Boolean
Dim y As Integer
For Each r In .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
If r <> "" Then
On Error Resume Next
Key = Trim(r.Text)
If Key = "LIABILITIES" Then
IsLiability = True
End If
data = getLedgerArray(cLedger(Key))
If Err.Number = 0 Then
Set list = cLedger(Key)
x = cLedger(Key).Count
With r.Offset(2).Resize(x, 3)
.Insert Shift:=xlDown, CopyOrigin:=r.Offset(1)
.Offset(-x).Value = data
If IsLiability Then
.Offset(0, 2).Resize(1, 1).FormulaR1C1 = "=""Bal. "" & TEXT(SUM(R[-" & x & "]C:R[-1]C)-SUM(R[-" & x & "]C[1]:R[-1]C[1]),""$#,###"")"
' LOOK HERE FOR Y
y = Application.Evaluate("=SUM(R[-" & x & "]C:R[-1]C)-SUM(R[-" & x & "]C[1]:R[-1]C[1])")
Debug.Print "Common Stock Balance Equals "; y
Else
.Offset(0, 1).Resize(1, 1).FormulaR1C1 = "=""Bal. "" & TEXT(SUM(R[-" & x & "]C:R[-1]C)-SUM(R[-" & x & "]C[1]:R[-1]C[1]),""$#,###"")"
End If
r.Offset(1).EntireRow.Delete
End With
End If
On Error GoTo 0
End If
Next
End With
Application.ScreenUpdating = True
End Sub
Function getLedgerArray(c As Collection)
Dim data
Dim x As Long
ReDim data(1 To c.Count, 1 To 3)
For x = 1 To c.Count
data(x, 1) = c(x)(0)
data(x, 2) = c(x)(1)
data(x, 3) = c(x)(2)
Next
getLedgerArray = data
End Function
Here is a solution that I was able to figure out, though I am not sure if it is the most efficient. In line before the formula is set, I set a Range named BalanceCell to the cell where the formula will be written. I then used the Mid Function to get the string number value from the cell (since the length of "Bal. " is always 5 characters) after the formula is put into BalanceCell.
If IsLiability Then
Set BalanceCell = .Offset(0, 2).Resize(1, 1)
BalanceCell.FormulaR1C1 = "=""Bal. "" & TEXT(SUM(R[-" & x & "]C:R[-1]C)-SUM(R[-" & x & "]C[1]:R[-1]C[1]),""$#,###"")"
y = Mid(BalanceCell.Value, 6, Len(BalanceCell.Value))
Debug.Print "Common Stock Balance is "; y

excel vba macro to match cells from two different workbooks and copy and paste accordingly

i have 2 workbooks, workbook A and workbook B. Each workbook has a table. workbook A has 2 columns. All three columns are filled.
product_id
Machine_number and
Workbook B has the same 2 columns but only one column, Product_id, is filled. The other 1 column is vacant.
I need to match the cells of product_id of both workbooks. If the product_id found in workbook A matches workbook B, then the machine number of that product id should be copied from workbook A to workbook B.
I have performed this using this code:
Sub UpdateW2()
Dim w1 As Worksheet, w2 As Worksheet
Dim c As Range, FR As Long
Application.ScreenUpdating = False
Set w1 = Workbooks("workbookA.xlsm").Worksheets("Sheet1")
Set w2 = Workbooks("workbookB.xlsm").Worksheets("Sheet1")
For Each c In w1.Range("A2", w1.Range("A" & Rows.Count).End(xlUp))
FR = 0
On Error Resume Next
FR = Application.Match(c, w2.Columns("A"), 0)
On Error GoTo 0
If FR <> 0 Then w2.Range("C" & FR).Value = c.Offset(, 0)
Next c
Application.ScreenUpdating = True
End Sub
There is a cell that says "machine 4" in product number column. This cell does not get copied and pasted alongside the corresponding product_id value in workbook B.
The rest of the machine numbers for the product ids get copied and pasted accordingly.
These are the screenshots of results
The first screenshot is
Workbook B
The second screenshot is
Workbook A
I have no idea why this happens, can someone please give me the reason for this?
................................................................................
UPDATE
I found that the issue ive descriped in the question arises when the product_id(style_number) repeats.
Say if product_id GE 55950 is present in 2 cells,in both workbooks. Then when i execute the macro only one of the cells is detected.
I tried the coding in both answers but neither solved this problem.
Below is a screenshot of the results.
In the screenshots the cell with machine 7 is not shown. Can someone tell me why this happens?
try this
Sub UpdateW2()
Dim Dic As Object, key As Variant, oCell As Range, i&
Dim w1 As Worksheet, w2 As Worksheet
Set Dic = CreateObject("Scripting.Dictionary")
Set w1 = Workbooks("workbookA.xlsm").Sheets("Sheet1")
Set w2 = Workbooks("workbookB.xlsm").Sheets("Sheet1")
i = w1.Cells.SpecialCells(xlCellTypeLastCell).Row
For Each oCell In w1.Range("D2:D" & i)
If Not Dic.exists(oCell.Value) Then
Dic.Add oCell.Value, oCell.Offset(, -3).Value
End If
Next
i = w2.Cells.SpecialCells(xlCellTypeLastCell).Row
For Each oCell In w2.Range("A2:A" & i)
For Each key In Dic
If oCell.Value = key Then
oCell.Offset(, 2).Value = Dic(key)
End If
Next
Next
End Sub
UPDATE AGAINST NEW REQUIREMENTS
use this
Sub UpdateW2()
Dim key As Variant, oCell As Range, i&, z%
Dim w1 As Worksheet, w2 As Worksheet
Dim Dic As Object: Set Dic = CreateObject("Scripting.Dictionary")
Dim Dic2 As Object: Set Dic2 = CreateObject("Scripting.Dictionary")
Set w1 = Workbooks("workbookA.xlsm").Sheets("Sheet1")
Set w2 = Workbooks("workbookB.xlsm").Sheets("Sheet1")
'-------------------------------------------------------------------------
'get the last row for w1
i = w1.Cells.SpecialCells(xlCellTypeLastCell).Row
'-------------------------------------------------------------------------
' fill dictionary with data for searching
For Each oCell In w1.Range("D2:D" & i)
'row number for duplicates
z = 1: While Dic.exists(oCell.Value & "_" & z): z = z + 1: Wend
'add data with row number to dictionary
If Not Dic.exists(oCell.Value & "_" & z) Then
Dic.Add oCell.Value & "_" & z, oCell.Offset(, -3).Value
End If
Next
'-------------------------------------------------------------------------
'get the last row for w2
i = w2.Cells.SpecialCells(xlCellTypeLastCell).Row
'-------------------------------------------------------------------------
'fill "B" with results
For Each oCell In w2.Range("A2:A" & i)
'determinate row number for duplicated values
z = 1: While Dic2.exists(oCell.Value & "_" & z): z = z + 1: Wend
'search
For Each key In Dic
If oCell.Value & "_" & z = key Then
oCell.Offset(, 2).Value = Dic(key)
End If
Next
'correction of the dictionary in case
'when sheet "A" has less duplicates than sheet "B"
If oCell.Offset(, 2).Value = "" Then
Dic2.RemoveAll: z = 1
For Each key In Dic
If oCell.Value & "_" & z = key Then
oCell.Offset(, 2).Value = Dic(key)
End If
Next
End If
'add to dictionary already passed results for
'the next duplicates testing
If Not Dic2.exists(oCell.Value & "_" & z) Then
Dic2.Add oCell.Value & "_" & z, ""
End If
Next
End Sub
output results below
I tried to replicate your workbooks, I believe they go something like this
Before
After
Code changes are minor,
Sub UpdateW2()
Dim w1 As Worksheet, w2 As Worksheet
Dim c As Range, FR As Long
Application.ScreenUpdating = False
Set w1 = Workbooks("BookOne.xlsm").Worksheets("Sheet1")
Set w2 = Workbooks("BookTwo.xlsm").Worksheets("Sheet1")
For Each c In w1.Range("D2", w1.Range("D" & Rows.Count).End(xlUp))
FR = 0
On Error Resume Next
FR = Application.Match(c, w2.Columns("A"), 0)
On Error GoTo 0
If FR <> 0 Then w2.Range("C" & FR).Value = c.Offset(, -3)
Next c
Application.ScreenUpdating = True
End Sub