CountIf Application or object defined error - vba

I've got a code that keeps on returning a run-time error 1004 - Application-defined or object-defined error. I've tried stepping through the individual parts of the worksheetfunction.countif function, and they all work fine separately.
However, when I put them together, they fail.
The code is:
s = 2
While Cells(s - 1, 1) <> vbNullString
Rows(s & ":" & s + 3).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range(Cells(s, 1), Cells(s + 3, 1)).Select
Selection.Rows.Group
Cells(s, 1) = "A"
Cells(s + 1, 1) = "B"
Cells(s + 2, 1) = "C"
Cells(s + 3, 1) = "D"
r = 3
q = vbNullString
p = vbNullString
n = s
While n < s + 5
While r <= v
M = 1
If Cells(n, 1) = "A" Then
q = 5
p = 12
ElseIf Cells(n, 1) = "B" Then
q = 18
p = 25
ElseIf Cells(n, 1) = "C" Then
q = 31
p = 38
ElseIf Cells(n, 1) = "D" Then
q = 44
p = 51
End If
While M <= u
l = vbNullString
l = WorksheetFunction.CountIf(Worksheets("IT Teams").Range(Cells(q, M), Cells(p, M)), Worksheets("Players IT").Cells(s + 4, 1))
If Not IsError(l) Then
Cells(n, r) = l
Else
Cells(n, r) = vbNullString
End If
M = M + 5
r = r + 1
Wend
Wend
n = n + 1
r = 3
Wend
s = s + 5
Wend
All variables have been declared as Variants.
Edit: for clarity. Error occurs at:
l = WorksheetFunction.CountIf(Worksheets("IT Teams").Range(Cells(q, M), Cells(p, M)), Worksheets("Players IT").Cells(s + 4, 1))

The problem is the way you declare the ranges. You should always include the sheet, otherwise you get this error, if you use more than one sheet (or if you use one, but it is not the active one).
Like this:
With ActiveSheet
While Cells(s - 1, 1) <> vbNullString
.Rows(s & ":" & s + 3).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
.Range(.Cells(s, 1), .Cells(s + 3, 1)).Select
Selection.Rows.Group
.Cells(s, 1) = "A"
.Cells(s + 1, 1) = "B"
.Cells(s + 2, 1) = "C"
.Cells(s + 3, 1) = "D"
Wend
End With
Pay attention to the dots.
In general, declare the sheets and then use them:
'Option Explicit - start using option explicit
Sub test()
Dim wksA As Worksheet
Dim wksIT As Worksheet
Set wksA = ThisWorkbook.ActiveSheet
Set wksIT = ThisWorkbook.Worksheets("IT Teams")
s = 2
While Cells(s - 1, 1) <> vbNullString
wksA.Rows(s & ":" & s + 3).Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
wksA.Range(wksA.Cells(s, 1), wksA.Cells(s + 3, 1)).Select
Selection.Rows.Group
wksA.Cells(s, 1) = "A"
wksA.Cells(s + 1, 1) = "B"
wksA.Cells(s + 2, 1) = "C"
wksA.Cells(s + 3, 1) = "D"
Wend
With wksIT
While M <= u
l = vbNullString
l = WorksheetFunction.CountIf(.Range(.Cells(q, M), _
.Cells(p, M)), .Cells(s + 4, 1))
If Not IsError(l) Then
.Cells(n, r) = l
Else
.Cells(n, r) = vbNullString
End If
M = M + 5
r = r + 1
Wend
End With
End Sub
Concerning your case, I am about 80% sure, that you get the error somewhere here:
l = WorksheetFunction.CountIf(Range(Cells(q, M), Cells(p, M)), Cells(s + 4, 1))
In general, never assume which worksheet your code is operating on and explicitly define it in your code.
Concerning the place where you get the error, it should be simply like this:
Set wksA = ThisWorkbook.ActiveSheet
Set wksIT = ThisWorkbook.Worksheets("IT Teams")
Set wksPl = ThisWorkbook.Worksheets("SomePlayers")
l = WorksheetFunction.CountIf(wksIT.Range(wksIT.Cells(q, M), wksIT.Cells(p, M)), _
wksPl.Cells(s + 4, 1))

Related

Excel vba For Each & For loop

lastColumn_Of_PO_line_Big_Table = Sheets("PO_line_Big_Table").UsedRange.Columns.Count + 1
a = Dict_Metadata.Keys
For Each b In a
For i = 1 To UBound(Arr_PO_line_Big_Table)
If Arr_PO_line_Big_Table(i, 1) = b Then
With Worksheets("PO_line_Big_Table")
nextRow = Sheets("Final_Result").Cells(Sheets("Final_Result").Rows.Count, 1).End(xlUp).row + 1
'.Cells(nextRow, "A") = strKey
'.Cells(i + 1, lastColumn_Of_PO_line_Big_Table) = "YES"
Union(.Cells(i + 1, "E"), .Cells(i + 1, "K"), .Cells(i + 1, "L"), .Cells(i + 1, "M")).Copy
Sheets("Final_Result").Range("B" & nextRow).PasteSpecial
End With
End If
Next
Next
Could someone please tell me why it doesn't paste the value in sheet "PO_line_Big_Table" to sheet Final_Result, thank you in advanced!!

Excel Search VBA macro

I have been given the task of searching through a large volume of
data. The data is presented identically across around 50 worksheets. I
need a macro which searches through all these sheets for specific
values then copies certain cells to a table created in a new workbook.
The macro also needs to create the table headings when it is run.
It must Search column G For the Value 9.1 Then certain information
must be copied to corresponding columns in the table
FHA Ref = Same row value from column G
Engine Effect = Same row value from column F
Part Number = Always cell J3
Part Name = Always cell C2
FM ID = Same Row value from Column B
Failure Mode & Cause = Same Row Value from Column C
FMCN = Same Row Value From Column C"`
If it is a hassle to create the new workbook with these column
headings then I would be quite happy to create the headings myself in
the worksheet and just have the macro search for and copy the data to
the rows corresponding to the headings.
If any help or backup files are needed I would be more than happy to
provide these.
the code I have at the moment is based on a userform also ideally I would do away with this and just search all sheets
Public Sub createWSheet(module, srcWBook)
Dim i
i = 0
srcWB = srcWBook
For Each ws In Workbooks(srcWBook).Worksheets
i = i + 1
If ws.Name = module Then
MsgBox ("A worksheet with for this module already exists")
Exit Sub
End If
Next ws
Workbooks(srcWBook).Activate
Worksheets.Add after:=Worksheets(i)
ActiveSheet.Name = module
Cells(2, 2) = "FHA Ref"
Cells(2, 3) = "Engine Effect"
Cells(2, 4) = "Part No"
Cells(2, 5) = "Part Name"
Cells(2, 6) = "FM ID"
Cells(2, 7) = "Failure Mode & Cause"
Cells(2, 8) = "FMCN"
Cells(2, 9) = "PTR"
Cells(2, 10) = "ETR"
Range(Cells(2, 2), Cells(2, 10)).Font.Bold = True
Range(Cells(1, 2), Cells(1, 10)) = "Interface"
Range(Cells(1, 2), Cells(1, 10)).MergeCells = True
Range(Cells(1, 2), Cells(1, 10)).Font.Bold = True
Workbooks(srcWBook).Activate
End Sub
Dim mainWB, srcWBook
Dim headerLeft, headerTop, headerBottom, headerRight
Dim nTargetFMECA, nPartID, nLineID, nPartNo, nPartName, nQTY, nFailureMode, nAssumedSystemEffect, nAssumedEngineEffect
Dim item As String
Dim mDest
Dim selections(100)
Public Sub controlCopyFMs(mWB, sWB, module)
Dim i
mainWB = mWB
srcWBook = sWB
mDest = 2
nTargetFMECA = 0
nPartID = 0
nLineID = 0
nPartNo = 0
nPartName = 0
nQTY = 0
nFailureMode = 0
nAssumedSystemEffect = 0
nAssumedEngineEffect = 0
For i = 0 To TestForm.LBSelected.ListCount - 1
Call copyFMs(module, selections(i))
Next i
End Sub
Public Sub copyFMs(module, comp)
Dim mSrc
Workbooks(srcWBook).Sheets(comp).Select
If exploreHeader(comp) = 0 Then
Exit Sub
End If
mSrc = headerBottom + 3
While Cells(mSrc, nSrc).Text <> ""
If Cells(mSrc, nIndication).Text <> "-" Then
If Cells(mSrc, nIndication).Text <> "" Then
Workbooks(mainWB).Worksheets(module).Cells(mDest, 2) = Cells(mSrc, nTargetFMECA).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 3) = Cells(mSrc, nPartID).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 4) = Cells(mSrc, nLineID).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 5) = Cells(mSrc, nPartNo).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 6) = Cells(mSrc, nPartName).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 7) = Cells(mSrc, nQTY).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 8) = Cells(mSrc, nFailureMode).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 9) = Cells(mSrc, nAssumedEngineEffect).Value
Workbooks(mainWB).Worksheets(module).Cells(mDest, 10) = Cells(mSrc, nAssumedSystemEffect).Value
mDest = mDest + 1
End If
End If
mSrc = mSrc + 2
Wend
End Sub
Public Function exploreHeader(comp)
Dim m, n
m = 1
n = 1
While ((InStr(1, Cells(m, n).Text, "Engine Programme:", vbTextCompare) <= 0) Or (InStr(1, Cells(m, n).Text, "BR700-725", vbTextCompare) <= 0)) And n < 10
If m < 10 Then
m = m + 1
Else
n = n + 1
m = 1
End If
Wend
headerTop = m
headerLeft = n
While StrComp(Cells(m, n).Text, "ID", vbTextCompare) <> 0 And StrComp(Cells(m, n).Text, "Case No.", vbTextCompare) <> 0
m = m + 1
Wend
headerBottom = m - 1
While Cells(m, n).Borders(xlEdgeBottom).LineStyle = xlContinuous
n = n + 1
Wend
headerRight = n - 1
m = headerTop
n = headerLeft
Do
If n > headerRight Then
n = headerLeft
m = m + 1
End If
If InStr(1, Cells(m, n).Value, "Item No.:", vbTextCompare) > 0 Then
item = Right(Cells(m, n).Value, Len(Cells(m, n).Value) - InStr(1, Cells(m, n).Value, ":", vbTextCompare))
Cells(m, n).Select
Exit Do
End If
n = n + 1
Loop While m <= headerBottom
m = headerBottom + 1
n = headerLeft
While n <= headerRight
If StrComp(Cells(m, n).Value, "ID", vbTextCompare) = 0 Then
nID = n
End If
If StrComp(Cells(m, n).Value, "Mitigation", vbTextCompare) = 0 Then
nMitigation = n
End If
If StrComp(Cells(m, n).Value, "Remarks", vbTextCompare) = 0 Then
nRemarks = n
End If
If StrComp(Cells(m, n).Value, "FMCN", vbTextCompare) = 0 Then
nFMCN = n
End If
If StrComp(Cells(m, n).Value, "Indication", vbTextCompare) = 0 Then
nIndication = n
End If
If StrComp(Cells(m, n).Value, "Crit", vbTextCompare) = 0 Then
nFMCN = n
End If
If StrComp(Cells(m, n).Value, "Detect", vbTextCompare) = 0 Then
nIndication = n
End If
If StrComp(Cells(m, n).Value, "Functional Description", vbTextCompare) = 0 Then
nMitigation = n
End If
n = n + 1
Wend
exploreHeader = 1
End Function
Public Sub initSelections()
For i = 0 To 99
selections(i) = ""
Next i
End Sub
Public Sub loadSelection(comp, i)
selections(i) = comp
End Sub
Public Sub deleteSelection(i)
While selections(i) <> ""
selections(i) = selections(i + 1)
i = i + 1
Wend
End Sub
I hope this can help more. This code may not work 100% but it should be good enough to guide you. Let me know if you have questions.
Dim WS As Worksheet
Dim Results(7, 1000000) As String ''Didn't know what is a good data type or how many possible results
Dim ColValue() As Variant
Dim I, II, ResultCt As Long
ResultCt = 0
For Each WS In ActiveWorkbook.Worksheets ''This should get all your result and information into the Results Array
ColValue = ActiveSheet.Range(Cells(2, 7), Cells(WS.UsedRange.Rows.Count, 7)).Value ''This put all of column G into an array
For I = 0 To UBound(ColValue)
If ColValue(I, 1) = "9.1" Then
Results(0, ResultCt) = Cells(I + 1, 7).Value ''I think it is off by 1, but if not remove the +1
Results(1, ResultCt) = Cells(I + 1, 6).Value
Results(2, ResultCt) = Cells(3, 10).Value
Results(3, ResultCt) = Cells(2, 3).Value
Results(4, ResultCt) = Cells(I + 1, 2).Value
Results(5, ResultCt) = Cells(I + 1, 3).Value
Results(6, ResultCt) = Cells(I + 1, 3).Value
ResultCt = ResultCt + 1
End If
Next
Next WS
''At this point us your code to create the worksheet and name it
''starting from the line Workbooks(srcWBook).Activate
''Then Set the Active cell to where ever you want to start putting the data and have something like
For I = 0 To UBound(Results, 2)
For II = 0 To UBound(Results)
ActiveCell.Offset(I, II).Value = Results(I, II) ''This assumes you put the information into Result in the order you want it printed out
Next
Next

Runtime Error "9" Subscript out of range

I have a great problem. I have a macro that does not run since the last week and I do not know why? I'm getting always the error: "Runtime Error 9 ...."
I know there must be a problem with the renames or arrays but I do not find anything.
Could you please check this code, maybe you can find the problem.
Thanks in advance!
Regards, Krisztian
It is just a part of the big macro.
The error is in the 8th row when "k" would be = "10"
Ubound is teoretically "9" (??)
EditRow(k) = EditRow(k) + (insdels * (k - 1))
'Populate input sheet
insdels = 0
For i = 1 To UBound(EditRow)
If FAT_Blocks(i).Range_Name <> "Absent_from_BCM" Then ' only process the blocks that were present
k = FAT_Blocks(i).GPI_Block_Number 'ERROR***************************************************************************
EditRow(k) = EditRow(k) + (insdels * (k - 1))
For m = 1 To FAT_Blocks(i).Rows
If FAT_Blocks(i).Data(m, 1) <> 0 Then ' ignore rows with zero cost/revenue in year 1
If GPIsheet.Cells(EditRow(k), 2).Interior.ColorIndex <> new_CI Then
new_InsDel (1)
insdels = insdels + 1
EditRow(k) = EditRow(k) + (k - 1)
End If
If FAT_Blocks(i).Row_Title(m) Like "*One Time*" Then
y = 0
ElseIf FAT_Blocks(i).Row_Title(m) Like "*Recurring*" Then
y = 1
Else
y = 2
End If
With GPIsheet
.Range("Original_Import_Data").Offset(EditRow(k) - 1, 0).ClearContents ' clear any mung before updating
' fill the "new_CI" coloured cells on the left
.Cells(EditRow(k), 2).value = BCMid & " " & FAT_Blocks(i).Row_Title(m) ' row description
.Cells(EditRow(k), 3).value = FAT_Blocks(i).Data(m, 1) ' unit value
.Cells(EditRow(k), 4).value = change_pc(y) ' change %
.Cells(EditRow(k), 5).value = change_year(y) ' change year
.Cells(EditRow(k), 6).value = vol_driver(y) ' volume driver
' fill the grey stuff on the right
With .Range("Original_Import_Data").Offset(EditRow(k) - 1, 0)
.Cells(1, 1) = yr ' Contract length
.Cells(1, 2) = BCMid ' BCM unique id
For j = 1 To yr
.Cells(1, 2 + j) = FAT_Blocks(i).Data(m, j) ' data for corresponding year
Next
End With
End With
EditRow(k) = EditRow(k) + 1
End If
Next m
End If
Next i

Macro incorrectly deleting table lines

I've got a macro that I run to add lines to a table, this information comes from a sql database.
My problem is, when I step through the macro it works absolutely fine and does exactly what it's supposed to. However, when I run the macro, lines go missing.
Anyone experienced something similar/any suggestions?
Thanks in advance
Tom
Sub BOMpart()
Dim NoRow, SupRow, i, j, k, h As Integer
Application.ScreenUpdating = False
NoCol = Range("Data").Columns.Count
' Reset Data Range
Application.DisplayAlerts = False
If Range("Data").Rows.Count > 1 Or Range("Data").Cells(1, 1) <> "" Then
Range("Data").Delete
End If
If Range("Supplier").Rows.Count > 1 Or Range("Supplier").Cells(1, 1) <> "" Then
Range("Supplier").Delete
End If
If NoCol > 3 Then
For a = NoCol To 4 Step -1
Range("Data").Columns(a).Delete
Next a
End If
Application.DisplayAlerts = True
' Initiate level counter
j = 1
k = 1
' Set up Level 1 BOM
part = Application.InputBox(prompt:="Enter top level part number:")
Range("Supplier").Cells(1, 1) = part
SupRow = Range("Supplier").Rows.Count
If part = False Then
End
Else
Sheets("BOMs").ListObjects( _
"BOMs").Range. _
AutoFilter Field:=1, Criteria1:=part, Operator:=xlAnd
Range("BOMs").Columns(4).SpecialCells(12).Copy Destination:=Range("Data").Columns(1)
Range("BOMs").Columns(4).SpecialCells(12).Copy Destination:=Range("Supplier").Cells(SupRow + 1, 1)
End If
Application.Wait Now + TimeValue("00:00:05")
' Part Description and FAI
NoRow = Range("Data").Rows.Count
For i = 1 To NoRow
part = Range("Data").Cells(i, k)
Sheets("Inventory").ListObjects( _
"Inventory").Range. _
AutoFilter Field:=1, Criteria1:=part, Operator:=xlAnd
Range("Inventory").Columns(4).SpecialCells(12).Copy Destination:=Range("Data").Cells(i, k + 1)
Range("Inventory").Columns(72).SpecialCells(12).Copy Destination:=Range("Data").Cells(i, k + 2)
Next i
' Input additional Levels
Do Until Range("Data").Rows.Count = Application.CountIf(Range("Data").Columns(k), "N/A")
NoRow = Range("Data").Rows.Count
NoCol = Range("Data").Columns.Count
j = j + 1
Sheets("BOM Data").Cells(1, NoCol + 1) = "Level " & j & " Pt No:"
Sheets("BOM Data").Cells(1, NoCol + 2) = "Level " & j & " Pt Desc."
Sheets("BOM Data").Cells(1, NoCol + 3) = "Level " & j & " FAI Req"
k = k + 3
On Error Resume Next
For i = NoRow To 1 Step -1
If Range("Data").Cells(i, k - 3) <> "N/A" Then
SupRow = Range("Supplier").Rows.Count
part = Range("Data").Cells(i, k - 3)
Sheets("BOMs").ListObjects( _
"BOMs").Range. _
AutoFilter Field:=1, Criteria1:=part, Operator:=xlAnd
nopart = Range("BOMs").SpecialCells(xlVisible).Rows.Count
If nopart > 0 Then
Rows(i + 2).Resize(nopart - 1).Insert
Range("Data").Range(Cells(i, 1), Cells(i, k - 1)).Copy Destination:=Range("Data").Range(Cells(i, 1), Cells(i + nopart - 1, k - 1))
Range("BOMs").Columns(4).SpecialCells(12).Copy Destination:=Range("Data").Cells(i, k)
Range("BOMs").Columns(4).SpecialCells(12).Copy Destination:=Range("Supplier").Cells(SupRow + 1, 1)
Else
Range("Data").Cells(i, k) = "N/A"
End If
Else
Range("Data").Cells(i, k) = "N/A"
End If
nopart = 0
Next i
On Error GoTo 0
NoRow = Range("Data").Rows.Count
For i = 1 To NoRow
If Range("Data").Cells(i, k) <> "N/A" Then
part = Range("Data").Cells(i, k)
Sheets("Inventory").ListObjects( _
"Inventory").Range. _
AutoFilter Field:=1, Criteria1:=part, Operator:=xlAnd
Range("Inventory").Columns(4).SpecialCells(12).Copy Destination:=Range("Data").Cells(i, k + 1)
Range("Inventory").Columns(72).SpecialCells(12).Copy Destination:=Range("Data").Cells(i, k + 2)
Else
Range("Data").Cells(i, k + 1) = "N/A"
Range("Data").Cells(i, k + 2) = "N/A"
End If
Next i
Loop
'Tidy Up
Application.DisplayAlerts = False
With Range("Data")
.Columns(NoCol + 3).Delete
.Columns(NoCol + 2).Delete
.Columns(NoCol + 1).Delete
End With
Application.DisplayAlerts = True
'Formatting
With Range("Data")
.Columns.AutoFit
End With
Sheets("Counter").Cells(1, 2) = 1
MsgBox "Done!"
Application.ScreenUpdating = True
End Sub
Firstly, you need to define the type of each variable in VBA even if they are on the same line. So right now your h variable is actually the only one defined as an integer. Not sure if this is causing your problem, but it should be fixed.
I see that in your Tidy Up section, you delete columns adjacent to the "Data" range, yet the "Data" range was potentially deleted in a previous conditional. I could see how this might cause unexpected deletes.
It would help if you tell us where the code is breaking.

Print in alternate rows in VBA

Need to print a table of any numbers using VBA in excel. i.e blank row after each row . Below iswhat i wrote to print a table in consecutive rows, But i dont know how can i print the result in alternate rows?
Sub table()
a = InputBox("Enter first no")
ActiveSheet.Cells.Clear
ActiveSheet.Cells(5, 4) = "TABLE OF " & a
For i = 1 To 10
c = a * i
ActiveSheet.Cells(i + 5, 4) = a
ActiveSheet.Cells(i + 5, 5) = "*"
ActiveSheet.Cells(i + 5, 6) = i
ActiveSheet.Cells(i + 5, 7) = "="
ActiveSheet.Cells(i + 5, 8).Value = c
next i
End Sub
Sub table()
a = InputBox("Enter first no")
n As Integer
n=6
ActiveSheet.Cells.Clear
ActiveSheet.Cells(5, 4) = "TABLE OF " & a
For i = 1 To 10
c = a * i
ActiveSheet.Cells(n, 4) = a
ActiveSheet.Cells(n, 5) = "*"
ActiveSheet.Cells(n, 6) = i
ActiveSheet.Cells(n, 7) = "="
ActiveSheet.Cells(n, 8).Value = c
n = n + 2
next i
End Sub
Change your row number calculation from
i + 5
to
(i * 2) + 4