Using DOM to find last row in HTML table - html

I'm developing a macro in Macro Express Pro that uses VBScript to scrub an HTML table to gather data. The data I'm gathering is in the FLN column. I want to build a list that the user can select from using the FLN, then they can gather the rest of the details within the row to use in other applications. The list looks like this:
My issue is that the list is only showing seven line items. The table I'm using for this example has eight lines. What is happening is I'm looping through to create this list, but when I get done copying the last FLN and go to the next row in the table (highlighted in yellow), I get an object required error.
I need to be able to read this line so that I can capture all rows in the table, then exit the loop when I reach the highlighted line. Unfortunately, the creators of the site with the table never named the table. There is a div that has an ID to it (div id="pnlBtn"). I've tried finding this ID, and receive an object error.
I am currently trying to find the last row in the table, but this is giving me an object error. I know the objIE.document part of my code is working as I was able to produce the list above. This was done by setting the counter I in the Do Until...Loop to 8, which only produces seven lines. If I set I to 9, I get an object error.
Here's the code I'm working with:
tdNode = 50
FLNDCC = objIE.Document.GetElementsByTagName("table")(0).GetElementsByTagName("td")(tdNode).GetElementsByClassName("txt_input1")(0).Value
I = 1
List = ""
intExitCount = 1
Do Until I = 8
If FLNDCC = NewFLNDCC Then
Exit Do
End If
If NewFLNDCC <> "" Then
FLNDCC = NewFLNDCC
End If
FLNDCC = I & ". " & FLNDCC
List = List & FLNDCC & vbCrLf
FLNDCC = Replace(FLNDCC, I & ". ", "")
TestRow = objIE.document.getElementsByTagName("tr")
For j = 0 To TestRow.length
MsgBox j
Next
I = I + 1
NewFLNDCC = objIE.Document.GetElementsByTagName("table")(0).GetElementsByTagName("td")(tdNode).GetElementsByClassName("txt_input1")(0).Value
If IsEmpty(NewFLNDCC) = True Then
Exit Do
End If
intExitCount = intExitCount + 1
If intExitCount = 10 Then
MsgBox "Do loop in VERIFY_HOV subroutine stuck in a loop." & vbCrLf & "Please submit an issue request with this message.", 48, "Stuck in Do Loop"
SetEverythingToNothing
End If
Loop
If I > 1 Then
Opt = InputBox("Please select the FLNDCC you want to work with:" & vbNewLine & List & vbNewLine, "Select an FLNDCC")
If IsEmpty(Opt) = True Then
Wscript.Echo "EXIT"
SetEverythingToNothing
End If
Opt = Opt - 1
tdNode = 50 + (Opt * 21)
Else
tdNode = 50
End If
FLNDCC = objIE.Document.GetElementsByTagName("table")(0).GetElementsByTagName("td")(tdNode).GetElementsByClassName("txt_input1")(0).Value
Is there a foolproof way to find the last row of a table that doesn't produce an object error?

I've found a solution. I didn't need to find the last row (highlighted in yellow), I just needed to avoid the error. The line that was creating the error was:
NewFLNDCC = objIE.Document.GetElementsByTagName("table")(0).GetElementsByTagName("td")(tdNode).GetElementsByClassName("txt_input1")(0).Value
On my ninth run through the loop, I was unable to find the txt_input1 value because it wasn't there. This gave me an object error. Here's how I solved it:
On Error Resume Next
NewFLNDCC = objIE.Document.GetElementsByTagName("table")(0).GetElementsByTagName("td")(tdNode).GetElementsByClassName("txt_input1")(0).Value
On Error goto 0
Now, I can have I set to 100 and, even though there are only 8 visible lines, it will kick out once txt_input1 is no longer available and print the list with all 8 lines.

Related

Item cannot be found in the collection correspoding to the requested name or ordinal

Trying to auto generate a sales id. But I don't know why I am getting this error.
Set qs = New ADODB.Recordset
qs.Open "select * from DailyRecords ", db, 3, 2
With qs
If .RecordCount = 0 Then
txtsalesID.Text = "S-0001"
Else
qs.MoveLast
txtsalesID.Text = "S-" & Format(Right(qs!SalesID, 4) + 1, "0000") // this line is producing the error
End If
I have even checked the database field name. It's the same as SalesID. I tried a lot and seeking for help
I think the problem is that you use RecordCount to check if the recordset is empty. The RecordCount leaves the cursor at the end of the recordset so you you will not be able to read data from the record, even if there are records. You should use EOF instead:
If .EOF Then
txtsalesID.Text = "S-0001"
Else
qs.MoveLast
txtsalesID.Text = "S-" & Format(Right(qs!SalesID, 4) + 1, "0000")
End If

Error when changing subreport recordsource: "You entered an expression that has an invalid reference to the property Form/Report"

I've got a form with a subreport on it, which occasionally references / changes the recordsource of said report. This has been working perfectly for months. I recently went back and started tweaking a few things in it, namely the tab order. I added in some code that checks which button was used to open it and changes the tab order based on that. As soon as I started testing if this was working or not, the Error
"You entered an expression that has an invalid reference to the
property Form/Report"
started appearing on every line that references the report recordsource. I've tried removing the code I added before the error appeared but that didn't cause the error to go away.
Example of code that gets the error:
Me.rRAM10x10.Report.RecordSource = "tRAM10x10"
Code that I added right before the error started:
If CurrentProject.AllForms("fHighRisk").IsLoaded = True Then
If Screen.ActiveControl.Name = "btnRAMimpact" Then
Me.btnForFocus.TabIndex = 0
ElseIf Screen.ActiveControl.Name = "btnRAMlhood" Then
Me.Tabordertest.TabIndex = 0
End If
End If
I did some research and found that this can be caused by the parent form not having any records, but that is not the case here. Other than what I posted above, no changes have been made to this form, the report, or any of the tables I'm setting its recordsource to since I finished changing it months ago.
The OnOpen Event of the Form:
Private Sub Form_Open(Cancel As Integer)
Dim sID As Integer
If CurrentProject.AllForms("fRiskAssessmentTest").IsLoaded = True Then
sID = Forms!fRiskAssessmentTest!fHighRisk!ScenarioID.Value
ElseIf CurrentProject.AllForms("fHighRisk").IsLoaded = True Then
sID = Forms!fHighRisk!ScenarioID.Value
Else
sID = 1
End If
Me.lblScenarioID.Caption = "Scenario " & sID
If CurrentProject.AllForms("fHighRisk").IsLoaded = True Then
If Screen.ActiveControl.Name = "btnRAMimpact" Then
Me.btnForFocus.TabIndex = 0
ElseIf Screen.ActiveControl.Name = "btnRAMlhood" Then
Me.Tabordertest.TabIndex = 0
End If
End If
clr1 = RGB(122, 197, 205)
clr2 = RGB(152, 245, 255)
'button colors
Dim lblName As String, btnName As String, lblCaption As String, Rating As
Integer, ctrl As Control
For Each ctrl In Me.Controls
If ctrl.ControlType = acCommandButton Then
ctrlName = ctrl.Name
Me.Controls(ctrlName).BackColor = clr2
End If
Next
'Darkens buttons if value is stored in table
For i = 1 To 5
lblName = "Vardisp" & i
lblCaption = Me.Controls(lblName).Caption
If IsNull(DLookup("[Variable Impact]", "tImpact", "scenarioID = " & sID &
" AND [Impact Variable] = """ & lblCaption & """ ")) Then
GoTo Skip_loop2
Else
Rating = DLookup("[Variable Impact]", "tImpact", "scenarioID = " &
sID & " AND [Impact Variable] = """ & lblCaption & """ ")
End If
For b = 1 To 10
If Rating = b Then
btnName = "Var" & i & "R" & b
Me.Controls(btnName).BackColor = clr1
End If
Next
Skip_loop2:
Next
End Sub
I'm pretty lost on what's causing this, so any help is greatly appreciated. Everything I've been able to find relating to it is caused by the parent forms recordset not having any records, and since that's not the case here, I'm struggling to find a direction to head with it.
Thanks!

Getting error (800A0035) referencing a line of code that has already been executed

I am writing a script right now which makes use of the File System Object to read a text file and later delete it. The part of the code in which this occurs I have written as a function. I have tested this function, along with some other functions which it depends on, and it works fine. But in the final product it is just one part of a script with 16 different functions/subroutines. After incorporating it into the final product, this file fails to work. Or, at least Windows script host tells me that it doesn't.
I have tested using Echo statements to track down the issue, since the line that WSH references should have executed properly, based on the fact that code after the line in question works when I run the script. I get an Echo when I echo after the function call (I have written a simple function to make the script wait before calling more functions, and the echo statement is after that, so the function definitely completes execution before the error occurs). I have also tried inserting an echo statement into the beginning of the next function to be called (literally directly after I instantiate the second function), and then I don't get an echo.
Here is the function in question. The line the error references is the one with Set objRECID.
Function PullRecords
Set objWSH = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strIP = "192.168.1.185"
strOutFileCMD = ".output OUT" & strIP & ".txt"
strOutFile = "C:\Users\" & GetLoggedOnUsername & "\Documents\SQLite3\" & "OUT" & strIP & ".txt" 'Output of each element grab
strCommand = "FROM ZCDataField WHERE RECORD_ID="
strRECIDPath = "C:\Users\" & GetLoggedOnUsername & "\Documents\SQLite3\" & "RECID" & strIP & ".txt" 'Output of GetRECID
strFinalCSVPath = "C:\Users\" & GetLoggedOnUsername & "\Documents\SQLite3\" & strIP & ".csv"
strSQLite3Path = "C:\Users\" & GetLoggedOnUsername & "\Documents\SQLite3\"
strProcName = "SQLite3.exe"
'Element ID's (for reference)
'intpt_item = "275426222"
'intpt_description = "275466434"
'intpt_custitem = "275466431"
'intpt_qty = "275466713"
'intpt_name = "275466710"
'intpt_date = "275435183"
'intpt_unixmil = "275578832"
'Options for text files
intForReading = 1
intForWriting = 2
intForAppending = 8
boolOverwriteTrue = True
boolOverwriteFalse = False
Set objCSV = objFSO.CreateTextFile(strFinalCSVPath,boolOverwriteTrue) 'Creates final CSV to be written to/
Set objRECID = objFSO.OpenTextFile(strRECIDPath,intForReading)
'Cycles through records
Do Until objRECID.AtEndOfStream
strRECID = objRECID.ReadLine
Set objELID = objFSO.OpenTextFile(strSQLite3Path & "Element IDs.txt",intForReading) 'Need this here so that script restarts at beginning of file each time.
'Cycles through elements
Do Until objELID.AtEndOfStream
Set objBAT = objFSO.CreateTextFile(strSQLite3Path & strIP & dblUnixT & ".bat",boolOverwriteTrue)
objBAT.Write ("cd /D C:\Users\" & GetLoggedOnUsername & "\Documents\SQLite3")
objBAT.WriteLine
objBAT.Write ("sqlite3 " & strIP & ".db < " & strIP & ".txt")
objBAT.Close
Set objBAT = Nothing
Set objCMDS = objFSO.CreateTextFile(strSQLite3Path & strIP & ".txt",boolOverwriteTrue)
objCMDS.Write (".mode tabs")
objCMDS.WriteLine
objCMDS.Write (strOutFileCMD)
objCMDS.WriteLine
strELID = objELID.ReadLine 'Gets ELEMENT_ID
objCMDS.Write ("SELECT VALUE_TXT,VALUE_NUM " & strCommand & strRECID & " AND ELEMENT_ID=" & strELID & ";") 'Gets element
objCMDS.WriteLine
objCMDS.Write (".exit") 'Exits SQLite3
objCMDS.Close
Set objCMDS = Nothing
objWSH.Run(strSQLite3Path & strIP & dblUnixT & ".bat")
'Makes script wait until BAT is done.
intRunning = 1
Do Until intRunning = 0
intRunning = IsRunning(strProcName)
Loop
Wscript.Sleep(500)
Set objOut = objFSO.OpenTextFile(strOutFile)
strOut = objOut.ReadLine
objOut.Close
Set objOut = Nothing
objCSV.Write strOut & ","
Loop
'Make string of line and then delete 1 character on right to get rid of ,. Then replace line.
objCSV.Write Chr(8)
objCSV.WriteLine
objELID.Close
Set objELID = Nothing
Loop
objCSV.Close
objRECID.Close
Set objCSV = Nothing
Set objRECID = Nothing
objFSO.DeleteFile strRECIDPath
'objFSO.DeleteFile strOutFile
InvertText(strFinalCSVPath)
PullRecords = strFinalCSVPath
Call FuncSubEndToken
End Function
In case it is useful, here is the FuncSubEndToken function that I call.
Function FuncSubEndToken
intFuncSubEndToken = 1
End Function
And here is how I am using it when I call the PullRecords Function.
Call PullRecords
'FuncSubEndTokenWait
Do Until intFuncSubEndToken = 1
Loop
intFuncSubEndToken = 0
Any help would be greatly appreciated.
Edit: I have tried using On Error Resume Next and I just get wscript hanging after the parts that I posted. It doesn't even enter the next function.
Edit 2: I have tried commenting out the line that deletes the file that is needed for the PullRecords function, even though that line is executed after the function is done with the file. It now is apparent that is calling this function twice and another function twice (and then it errors out part way through that). I have looked and both of these functions are only ever called once (and they are not in loops, so that is definitely not the issue). I do call a function and pass it the output of both of these functions, in the order that they seem to be running. But I am not here calling the functions themselves. But perhaps wscript thinks that I am?
Edit 3: I have deleted the function that uses the return of the other two functions (well, commented it out), and I still get the same issue.
So, I have now figured out the issue. It would seem that I was somewhat misinformed on how functions work when trying to get their output. I thought that you called a function and then the function name was the output. But, it would seem that you do not need to use a call statement to execute a function. So, while trying to use the output of my functions I have been inadvertently calling them.

Access 2007: Hide Data Labels on Chart Object via vba with 0 values?

I have a form in Access 2007 with a Stacked Bar Chart Object that is dynamically generated depending on the current date and outputs a PDF of the chart.
Everything generates and works fine, but what is happening is data labels are being applied even for series with a Null or 0 value. This leads to a mess of text in various places.
I'm looking for a way via VBA to remove any labels that belong to a series with no values.
I've tried ruling out null values from the SQL query and also setting the format options so the 0 values won't show. I have tried looping through the series and applying a label if the value is > 0, but if I set it to apply the series name it still puts it for blank values.
EDIT Current Code:
Option Compare Database
Private Sub Form_Load()
Dim tstChart As Graph.Chart
On Error GoTo Form_Load_Error
Set tstChart = [Forms]!testing!barEquip.Object
With tstChart
.HasTitle = True
.ChartTitle.Font.Size = 14
.ChartTitle.Text = VBA.Strings.MonthName(VBA.DatePart("m", VBA.Date()) - 1) & " " & VBA.DatePart("yyyy", VBA.Date()) & _
" Test Title"
For Each srs In .SeriesCollection
For Each pt In srs.Points
pt.DataLabel.Text = "Y"
Next
Next
End With
On Error GoTo 0
Exit Sub
Form_Load_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Form_Load of VBA Document Form_testing"
End Sub
I'm able to change each label, but I can't seem to figure out a way to check each point in the series points.
EDIT:
SOLVED
(Simple, but works fine)
Sub AdjustDataLabels(cht As Chart)
Dim srs As Series
Dim pt As Point
Dim vals As Variant
For Each srs In cht.SeriesCollection
'Apply Value labels
srs.ApplyDataLabels (xlDataLabelsShowValue)
For Each pt In srs.Points
'Check for empty labels
If pt.DataLabel.Text = "" Then
'Do nothing
Else
'Add Series Name then remove Value
pt.DataLabel.ShowSeriesName = True
pt.DataLabel.ShowValue = False
End If
Next
Next
End Sub
You are using a Graph.Chart instead of a Chart. They are more limited in what you can do with them, which is what I was afraid of. But perhaps this can help anyways.
The idea is to first ensure that the series data labels are being displayed.
Once we know they are displayed, iterate the points and selectively manipulate the point's DataLabel.Text property, based on it's DataLabel.Text property. I'm assuming the value here being displayed is 0, and that you simply want to hide labels if it's 0, and do nothing to the other labels.
Within your procedure we will call another sub to do this:
Set tstChart = [Forms]!testing!barEquip.Object
With tstChart
.HasTitle = True
.ChartTitle.Font.Size = 14
.ChartTitle.Text = VBA.Strings.MonthName(VBA.DatePart("m", VBA.Date()) - 1) & " " & VBA.DatePart("yyyy", VBA.Date()) & _
" Test Title"
Call AdjustDataLabels(tstChart) 'Call a procedure to modify the labels as needed
End With
So that code will now call on another sub-procedure:
Sub AdjustDataLabels(cht As Graph.Chart)
Dim srs As Graph.Series
Dim pt As Graph.Point
Dim vals As Variant
For Each srs In cht.SeriesCollection
'First, ensure the dataLabels are ON
srs.ApplyDataLabels
For Each pt In srs.Points
'Now, check the datalabels one by one, testing for your criteria
If pt.DataLabel.Text = " some condition " Then
'Criteria met, so blank out this datalabel
'pt.HasDataLabel = False
'OR:
pt.DataLabel.Text = vbNullString
Else
'If you need to make any adjustments to other labels,
' you can do that here.
' For example you could simply append the series name.
' Modify as needed.
pt.DataLabel.Text = pt.DataLabel.Text & " -- " & srs.Name
End If
Next
Next
End Sub
SOLVED: (Simple, but works fine) Thanks for all the help!
Sub AdjustDataLabels(cht As Chart)
Dim srs As Series
Dim pt As Point
Dim vals As Variant
For Each srs In cht.SeriesCollection
'Apply Value labels
srs.ApplyDataLabels (xlDataLabelsShowValue)
For Each pt In srs.Points
'Check for empty labels
If pt.DataLabel.Text = "" Then
'Do nothing
Else
'Add Series Name then remove Value
pt.DataLabel.ShowSeriesName = True
pt.DataLabel.ShowValue = False
End If
Next
Next
End Sub

Concatenating Null values in DCount query that compare to corresponding concatenated table fields

Using Access 2007.
I have to compare several data entry fields with their corresponding tables fields. If the fields match, do not add a new record. If not, add a new record with the values.
AnimalInfo Table fields
WHno (Wildlife Health Number)
Species
LETClr1 (Left Ear Tag Color 1)
LETNo1 (Left Ear Tag Number 1)
LETClr2 (Left Ear Tag Color 2)
LETNo2 (Left Ear Tag Number 2)
RETClr1 (Right Ear Tag Color 1)
RETNo1 (Right Ear Tag Number 1)
RETClr2 (Right Ear Tag Color 2)
RETNo2 (Right Ear Tag Number 2)
Form F_HotelForm unbound fields
txtSpecies
txtLETClr1
txtLETNo1
txtLETClr2
txtLETNo2
txtRETClr1
txtRETNo1
txtRETClr2
txtRETNo2
I am trying to create a DCount to check and see if there are any matching records. The animal's uniqueness is determined by its species and ear tag information. It can have one ear tag number and color, or four. (Some of the older data has none but I can't do anything about that! In those cases, a new record, i.e. new Wildlife Health Number will be generated)
This is what I want to accomplish with this form:
If there are no matching fields (DCount = 0) add a new record and update fields from the form into table.
If there is 1 matching record, then the animal's wildlife health number is displayed (in a new form eventually)
If there are multiple records, then these are displayed in another form and the user needs to pick the correct animal.
LETClr1 and LETNo1 are paired.
LETClr2 and LETNo2 are paired.
RETClr1 and RETNo1 are paired.
RETClr2 and RETNo2 are paired.
Any and all of these fields could have values or not. Left ear tag numbers and colors could have been entered as either LETClr1 or LETClr2 so I have to compare both LETClr1 and LETClr2 with the txtLETClr1 data entry. (This holds true for all paired fields)
Below is a sample of the script so far. It is very rudimentary as I am very new to this and am just trying to see what works.
Private Sub GenerateWHno_Click()
Dim rs As DAO.Recordset
If IsNull(Forms!F_HotelEntry!txtSpecies) Or (Forms!F_HotelEntry!txtSpecies) = "" Then
MsgBox "Species is a required field. Please enter a species"
Exit Sub
End If
MsgBox txtSpecies
SpeciesCount = DCount("[Species]", "AnimalInfo", "[Species]= '" & txtSpecies & "'AND [L_ET_Color1]='" & txtL_ET_Color1 & "' AND [L_ET_No1]='" & txtL_ET_No1 & "'")
If SpeciesCount > 1 Then
MsgBox SpeciesCount & " Greater than 1"
ElseIf SpeciesCount = 0 Then
MsgBox "You need a new WHno"
WHno = Nz(DMax("WHno", "AnimalInfo")) + 1
MsgBox WHno
Set rs = CurrentDb.OpenRecordset("AnimalInfo")
rs.AddNew
rs!WHno = WHno
rs!Species = txtSpecies
rs!L_ET_Color1 = txtL_ET_Color1
rs!L_ET_No1 = txtL_ET_No1
rs!R_ET_Color2 = txtR_ET_Color2
rs.Update
rs.Close
Else
End If
Forms!F_HotelEntry!txtSpecies = ""
Forms!F_HotelEntry!txtL_ET_Color1 = ""
Forms!F_HotelEntry!txtL_ET_No1 = ""
End Sub
So the problem is that I cannot concatenate NULL fields. The DCount only works if there is Non Null data in the form/table.
Any ideas as to how I can work around this?
Many thanks.
My comments are getting garbled so I am putting below original posting.
I copied the suggested code into module and rewrote query a couple of different way but still got error message: Run-time error 424. Object required
SpeciesCount = DCount("[Species]", "AnimalInfo", "[Species] = txtSpecies AND (is_null([L_ET_Color1],"""") = is_null(txtL_ET_Color1,""""))")
SpeciesCount = DCount("[Species]", "AnimalInfo", "[Species] = '" & txtSpecies & "'AND is_null([L_ET_Color1],"") ='" & is_null(txtL_ET_Color1, "") & "' AND [L_ET_No1]='" & txtL_ET_No1 & "'")
I have been tinkering with this for 3 hours and am no closer to a solution. What am I doing wrong?
In a module create the following function:
public function is_null(ctl as variant, nullreplace as string) as variant
if ctl is null then
is_null = nullreplace
else
is_null = ctl
end if
end function
In your query change your reference to a given field, yourField to is_null(yourField, "").
In a string enclosed in double quotes, this will need to be is_null(yourField, """") (it needs a double-quote to escape a double-quote, so 4 is 2 internally)