I'm writing a Windows Form App on VS2019 that will open an excel file and perform nested loop.
Basically, there are two lists of integer. The code is going to loop through every row to check if the value of cell A exist in any of the lists, then assign a string to cell B.
The list in the original code has around 400 elements, but I cut it down to post here. Then something interesting happens. When I run the original code with 400+ elements, it loops the row and stopped halfway, then it gives me the "Exception from HRESULT: 0x800AC472". However, when I run the codes below it has no error.
So I thought if the huge list is the problem. I wonder if any of you had met this scenario before and how you solve it.
[Update] I've added more elements to the list and tried to run it. It did throw the same exception. I also tried reducing the amount of the elements and run again and it worked without error. So I guess it's because of the amount of element.
Private Sub generateZone(ByVal worksheet As Object)
'Initialise Excel Object
xlsApp = New Excel.Application
'Open file
xlsWorkBook = xlsApp.Workbooks.Open("File location")
'Open worksheet(according to the spreadsheet)
xlsWorkSheet = xlsWorkBook.Worksheets("sheet1")
'Excel interaction setting
With xlsApp
.Visible = True
.Application.Visible = True
.DisplayAlerts = False
.EnableEvents = False
End With
Dim emZone1 As New List(Of Integer)(New Integer() {87371, 87390, 94614, 92000, 82898, 96500, 99124, 93260, 82496, 97858, 90323, 88083, 80770, 84186, 86318, 91922, 85987, 80635, 84079, 96691, 85578, 83108, 96081, 87642, 96703, 96692, 99193, 93039, 97003, 89374, 99252, 82305, 87907, 90966, 80517, 88471, 92395, 86109, 87112, 92849, 93853, 91136, 90512, 97143, 96105, 93966, 81136, 97218, 97816, 82525, 97714, 98175, 94940, 97262, 81750, 92075, 98905, 96199, 94072, 83841, 88243, 98375, 84142, 92818, 83527, 97446, 88632, 86542, 84768, 86283, 84910, 88986, 92802, 99145, 81487, 84729, 80010, 90896, 99418, 87545, 95937, 89904, 88073, 85255, 87285, 88442, 86325, 90223, 92048, 85160, 98768, 80283, 91273, 92077, 91043, 81409, 96042, 82536, 92726, 91980})
Dim emZone2 As New List(Of Integer)(New Integer() {86634, 92330, 95970, 95577, 87510, 89481, 94248, 93860, 81857, 82810, 93228, 80095, 94437, 84887, 88766, 92706, 92264, 88109, 91992, 82751, 94767, 95397, 96066, 91667, 94059, 89419, 82796, 82310, 86961, 85681, 93969, 81736, 81009, 97445, 80741, 92154, 84923, 86182, 91660, 90665, 81388, 87722, 94031, 94678, 84074, 80550, 82953, 81317, 95132, 92163})
'get last row
Dim lastRow As Integer
lastRow = worksheet.UsedRange.Rows.Count
'loop through every row
For i As Integer = 1 To lastRow
'get pronvice from column J
Dim province As String = worksheet.Range("J" & i).Value
If province = "Sabah" Or province = "Sarawak" Then
'check zone1
For Each zone1 As Integer In emZone1
If emZone1.Contains(worksheet.Range("L" & i).Value) Then
worksheet.Range("M" & i).Value = "Zone 1"
Else
'check zone2
For Each zone2 As Integer In emZone2
If emZone2.Contains(worksheet.Range("L" & i).Value) Then
worksheet.Range("M" & i).Value = "Zone 2"
' Exception from HRESULT: 0x800AC472 shows here
Else
'if not in both zone
worksheet.Range("M" & i).Value = "EM"
End If
Next
End If
Next
Else
'if not sabah and sarawak
worksheet.Range("M" & i).Value = "WM"
End If
Next
'releaseObject(xlsWorkSheet)
'releaseObject(xlsWorkBook)
'releaseObject(xlsApp)
End Sub
Not sure if this is the same but another SO post with this same error was resolved with the following answer:
"In my case, the exception was been thrown because my excel Interop tools was displaying a modal dialog (associated with a expired licence key - shame on me). If I closed the dialog (which was been displayed in the background) and then hit 'continue' in Visual Studio, the program was able to connect to the xlsx file and retrive data succesfully."
-mbmihura
Have you verified that no popups or anything are appearing?
Is your excel licensed as well?
If not this,
I would add a limit to your loop and try to find if there is a fixed number of iterations before the error, if so, then there is some default limit being imposed.
One final thought,
I have seen these interop excel calls not get properly disposed in a lot of examples which causes many excels to be stuck running in the background.
Check your task manager and ensure that isn't happening. If so, close them out and try your tests again.
I think you just need to check for empty cells before reading the value. Excel will throw an exception when the cell is empty and you try to parse it as a string
Dim xlsRange As Excel.Range = Nothing
' In your loop
xlsRange = DirectCast(xlsWorkSheet.Cells("J" & i), Excel.Range)
If xlsRange.Value IsNot Nothing Then
Dim province = xlsRange.Value.ToString()
End If
' /Loop
' always release it at the end
If xlsRange IsNot Nothing Then Marshal.ReleaseComObject(xlRange)
I still prefer loading everything into objects and operating on them after releasing all the Excel objects
I'am new to vba in excel. I managed to write a code which scrapes data from a given website and stores it in an excel worksheet. The code works almost every time i run it but sometimes i get an error:
Object variable or With block variable not set.
So it is very challenging to find out why. Also if you could help me out speeding the code (maybe not using clipboard to pastspecial the table, but I don't know how to use otherwise...). Also for you to know, once the error is promted if I click end and run the sub again, it runs without any problem. The error is promted (sometimes only, most of the time the sub works fine) in the specified line with this comment: 'This is the line which throws the error. I appreciate any kind of help guys, thank you in advance :).
The sub looks like this:
Sub PaData()
Dim c As Object, D As Object, H As Object, PID$, SD As Date, FC$, cf$
Set c = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
Set D = CreateObject("HTMLFile")
Set H = CreateObject("WinHTTP.WinHTTPRequest.5.1")
FC = "EXA" ' This is used to generate the website url
cf = VBMa ' This is another sub which works fine and i need it to get into the webiste
' Get the page
H.SetAutoLogonPolicy 0
H.SetClientCertificate "CURRENT_USER\MY\" & Environ("USERNAME")
H.Open "GET", "https://confidentialwebsite=" & FC
H.setRequestHeader "Cookie", cf
H.Send
H.waitForResponse
' Put the response into the HTML object
D.body.innerHTML = H.ResponseText
' Copy _only a given Table
c.setText D.getElementByID("giventable").outerHTML 'This is the line which throws the error
c.PutInClipBoard
' Paste into the sheet, remove hyperlinks and unMerge all data
Sheets("Pdata").Cells.Delete
Sheets("Pdata").[A1].PasteSpecial
Sheets("Pdata").Cells.Hyperlinks.Delete
Sheets("Pdata").Cells.UnMerge
'update time
Sheets("SM").Range("B1").Value = Sheets("Pdata").Range("D2").Value + 2 / 24
End Sub
When doing an HTTPRequest to a webserver, you should always verify the return status of this call using .Status (see: this )
An overview of the possible status numbers can be found here: https://httpstatuses.com/ or here: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_Informational_response
I am very new to VBA and still learning programming languages and coding. I came up with the following code for my project after reffering several online tutorials and threads. When I run the code I get an error message saying,Run-time Error: Type mismatch.If anyone of you experts could help me to find the error, it would be highly appreciated.
Thanks a lot in advance
Dim wsServiceRegistry As Worksheet, wsInhouseMaterialInventory As Worksheet
Dim updateCell As Range
Dim emptyRow As Long
With ThisWorkbook
Set wsServiceRegistry = .Worksheets("Service Registry")
Set wsInhouseMaterialInventory = .Worksheets("Inhouse Material Inventory")
End With
Set updateCell = wsInhouseMaterialInventory.Cells(Me.InhouseMaterialComboBox.ListIndex + 2, 4)
updateCell.Value = updateCell.Value - Val(Me.MaterialQuantityTextBox.Value)
If updateCell.Value < 1 Then updateCell.EntireRow.Delete: Exit Sub
The only line that can cause a type mismatch here is
updateCell.Value = updateCell.Value - Val(Me.MaterialQuantityTextBox.Value)
, depending on what the cell contains.
The first thing to find out, is if it is the cell you actually want and if it contains what you expect. Add these lines just above the line in question:
Debug.Print updateCell.Address
Debug.Print updateCell.Value
Press Ctrl+G to show the debug output and run it. If the output matches your expectation, then you'll have to use the Val function again, like this:
updateCell.Value = Val(updateCell.Value) - Val(Me.MaterialQuantityTextBox.Value)
forcing the updateCell to become something you can subtract from.
I am rather new at programming, and while learning Python also started experimenting with Excel VBA. I have an issue with the last one.
I have some large Excel sheets and tried to validate that data in specific columns matches data on another sheet in certain columns as they will be supposed to relate to each other by these values (and will be connected by a third value). To make this a bit more difficult, both of these columns may contain more than one value separated by "|". So, I have split these values in a list and I try to iterate through them to make sure all these values are set correctly, the connection will work fine.
All is fine as long as all is fine :) I have however an issue where there are two values in one of those columns and only one in the other. I would like this discrepancy to be noted on a sheet and then proceed to the next item.
The way that seemed to be applicable for me is to use "On Error GoTo ErrHandler", then note error on another sheet, and then user Resume to proceed.
Here is what I came up with:
For h = 0 To UBound(Split1())
For j = 1 To GetMaxRow("SpecificSheet", A)
On Error GoTo ErrHandler:
If Sheets("SpecificSheet").Cells(j, 1).Value = Split1(h) And Sheets("SpecificSheet").Cells(j, 2).Value = Split2(h) Then
DependencyOk = DependencyOk + 1
End If
Next j
Next h
ErrProceed:
Also ErrHandler is:
ErrHandler:
Sheets("Issues").Cells(x, 1) = "IssueDescription"
GoTo ErrProceed
It stops at line 2 with Subscript out of range for Split2(h) rather than moving on to ErrHandler and then ErrProceed. I have the feeling this must be something very obvious but I am just unable to get this working, and I am not able to find other way (like a try/except) in Excel VBA.
UPDATE:
Trying to clarify things a bit. The root of the issue is, that the Split2 list is shorter than Split1 - which is an issue with the input data and I'd like to capture this. I get the Split values from cells, where the values are separated by "|" characters:
CellValue = Sheets("SomeSheet").Cells(RowNumber, ColumNumber)
CellValueSplit() = Split(CellValue, "|")
And then iterate as:
For h = 0 To UBound(Split1())
So as Split1 moves on to the for example 3rd value, Split2 throws error and script stops. The best I was able to do so far was, that I let it proceed with the loop, but as this is a rather large sheet, it will fill the same error report ca. 200k times in this case, which I'd like to avoid. So I'd prefer it to proceed from after this loop once it hits out of range error, and proceed examining the next value.
Thank you for your help so far and in advance!
You have an issue with your syntax. The proper Error statement syntax is:
On Error GoTo <string>
On Error Resume Next
On Error GoTo 0
When using On Error GoTo <string> there is no ":" at the end. The ":" doesn't come into play until you create the target location. Example:
On Error GoTo Here
'// ---- Do something ---- //
Here:
'// ---- Handle the error ---- //
If you use On Error Resume Next, then you're telling the machine to ignore errors and proceed on to the next line of code.
When you useOn Error Return To 0, VBA will reset its error handling back to default. It's a good habit when using On Error Resume Next to insert On Error Return To 0 as soon as you no longer need it. On Error Resume Next has a real potential to break your code and make it behave strangely. Not to mention debugging can be a real nightmare. Check out the VBA manual from Microsoft for a more detailed explanation.
Finally, if your question is answered, you should mark it as answered.
vba-excelvbaexcel
The short and quick version is that VBA Error Handling Routine's only handle errors in the actual code execution, they do not fire when conditions expressed by the code are not met.
In your case, you do not need any error handling at all. In most cases it is actually best to avoid On Error GoTo .... There are cases where it's inevitable, but they are rare.
Try this IF THEN ELSE block:
If Sheets("SpecificSheet").Cells(j, 1).Value = Split1(h) And Sheets("SpecificSheet").Cells(j, 2).Value = Split2(h) Then
DependencyOk = DependencyOk + 1
Else
Sheets("Issues").Cells(x, 1) = "IssueDescription"
End If
Actually I have just found the issue. It was caused by a ":" left after an If statement a few rows earlier. I still don't really understand what it did, but I suggest not to reproduce it :)
I have a VBA function within a spreadsheet which operates on another spreadsheet that is opened in an earlier stage of my macro. The macro used to work fine but just recently has started causing a 1004 error ("Unable to get RoundDown property of the WorksheetFunction class") when it runs.
I believe I understand what the error would be caused by (a problem running RoundDown) but I cannot see why it is getting triggered in my macro and the odd part is that when I go into Debug mode and step through the code in the VBE the error does not recur (despite nothing obviously changing).
Does anyone have a similar experience of this sort of error occuring inconsistently and know what I could do to resolve it?
I'm reasonably VBA/Excel-savvy, but any suggestions on further steps to diagnose it would be appreciated. I am wondering if there is some issue with the opened spreadsheet not being ready but I cannot see how.
The code is here. The error occurs on the line marked with a comment.
Public Function GetDatesA(sWorkbookname As String, sSheetname As String, sCell As String) As Variant
Dim vDateList() As Variant
Dim currentCell As Range
Dim n As Long
Set currentCell = Workbooks(sWorkbookname).Worksheets(sSheetname).Range(sCell)
n = 0
Do
If Trim(currentCell.Value) = "" Then
Exit Do
Else
ReDim Preserve vDateList(0 To 1, 0 To n)
vDateList(0, n) = WorksheetFunction.RoundDown(currentCell.Value, 0) 'error occcurs on this line
vDateList(1, n) = currentCell.Column
'Debug.Print currentCell.Value
End If
Set currentCell = currentCell.Offset(0, 1)
n = n + 1
Loop While currentCell.Column < XL_LAST_COLUMN
GetDatesA = vDateList
End Function
Other details are:
Excel version: 2010
File being opened resides locally on my C: drive; my macro is in a spreadsheet on the network
File format for both files is .xls (i.e. Excel 2003) - I don't have the option of changing this
Windows 7 (not that I think it would be relevant)
Two points I've tried already are:
Substitute a different worksheet function (e.g. Min(currentCell)) and that also causes the same problem
Having the file open already seems to stop the problem - I wonder if there is some way that the workbook which is being opened (rather than my main workbook with the macro in it) is not enabled for macros and this is interfering. But even if this is the cause I'm not sure how to get around it!
Any ideas?
This error occurs often when any argument passed to the worksheet function is not of the correct type or simply doesn't make sense.
For example, I've had this problem when calling WorksheetFunction.Asin with an argument bigger than 1. In your case, I'd guess currentCell.Value is a non-numeric value or one not according to your region settings regarding numbers.
Yes, the error message is really misguiding.
I got the "Unable to get * property of WorksheetFunction Class" error using Transpose, MMult,MDterm, and MInverse functions.
I was able to get my code to run by putting "Option Base 1" in the Declarations (before the actual code) section of the particular Module in the Editer.
Excel assumes "Option Base 0" which will add an extra row and column of empty cells. This will cause the error to occur and isn't immediately obvious to see.
I have come accross this before, and for me it was becase the criteria range made no sense, as Andre said above.
See example formula below:
.Cells(11, i).Formula = Application.WorksheetFunction.CountIfs(Sheets("Sheet1").Range("AC8:C" & n), "S")
Have a look at the Range... it makes no sense. Amended the range from "AC8:C" to "AC8:AC" and it will work perfectly