VB6 execution with database is different when stepping through vs running - debugging

I've come across a weird scenario with the following code in a vb6 app:
Private database As dao.Database
Set database = openDaoDatabase([some valid database location], False)
createDBField database, "Table", "FirstRow", dao.dbInteger, 0, "0"
Public Sub createDBField(targetDB As dao.Database, strTable As String, strField As String, dbType As dao.DataTypeEnum, Size As Integer, strDefValue As String)
Dim td As dao.TableDef
Dim fld As dao.field
Set td = targetDB.TableDefs(strTable)
Set fld = td.CreateField(strField, dbType, 0)
If dbType = dao.DataTypeEnum.dbText Or dbType = dao.DataTypeEnum.dbMemo Then fld.AllowZeroLength = True
If strDefValue <> "" Then fld.DefaultValue = strDefValue
td.Fields.Append fld
Set td = Nothing
Set fld = Nothing
End Sub
When I step through, everything works and the new field is added to the database. However, when I simply run the application, the database becomes corrupted due to 'inconsistency'. I added some error handling and now get the error: "Unrecognized database format: [path]".
After searching the Microsoft database, I found a solution: http://support.microsoft.com/kb/238401. I'm using the Microsoft.Jet.OLEDB.4.0 provider, have SP6 installed and have a reference to the Microsoft DAO 3.6 Object Library, but it's still not working!
Any thoughts?
Update:
td.Fields.Append fld is the culprit. After removing all silent error handling, I was able to catch an error: "Run-time error 3343 Unrecognized Database Format". For some reason, I can just step over it though.

I suspect your problem is happening because of the AllowZeroLength property. I suspect the field should be added to the fields collection and the AllowZeroLength property updated.
After
td.Fields.Append fld
put something like the following:
Set tdfField = tabledef.Fields(strField)
Set prp = tdfField.CreateProperty("AllowZeroLength", dbboolean, True)
tdfField.Properties.Append prp
Note the above is aircode and not tested.
That said, it doesn't make a lot of sense to me for a text or MEMO field's AllowZeroLength property to default to True. After all, the front end user can't really visually distinguish between the NULL value and a zero length string value.

I don't see a call to database.close that might be the cause. If your VB app terminates abruptly that might leave the DB in an inconsistent state.

Which line is the error occurring on? Usually when I run into VB errors like this they are timing related. Stepping through gives enough time for something to finish processing. Try adding some sleep commands before the statement that is causing the error.

Related

Run-time error '91' when adding data to a record set

I want to insert some information into a database in VB6, but I get runtime error '91'.
My code:
Private sub btn_click()
Fname = txtFname.text
Adodc1.Recordset.AddNew
Adodc1.Recordset.Fields("Fname") = Fname
Adodc1.Recordset.Update
End sub
The debuger shows error on: Adodc.Recordset.AddNew
You haven't posted the rest of the code as to where the Adhoc1 variable is created etc...
This post suggests that the RecordSet has not been initialized prior to working with it, but it's hard to be more specific without the code.
Runtime error '91' is Object variable or With block variable not set, which is a slightly confusing way to say that your variable contains Nothing.
You either forgot to initialise the Adodc1 properly, or, and this is more likely, you need to initialise Adodc1.RecordSet to something useful (like a Set Adodc1.RecordSet = New RecordSet or related) before you can use it.
By the way you posted the code, I believe that you will populate a Recordset to insert into the database. Try as follows:
sub btn_click()
dim Adodc1 as adodb.recordset
set Adodc1 = new adodb.recordset
Fname = txtFname.text
Rs.Fields.Append "Fname", adVarChar, 20 'adVarChar = text, followed by the amount of characters
Adodc1.open()
Adodc1.Recordset.AddNew
Adodc1.Recordset.Fields("Fname") = Fname
Adodc1.Recordset.Update
End sub

VB6 - Items not adding to collection

I'm having problems building a collection of data. The problem code is as follows:
'Basic defitions are as follows:
Private mCol As Collection
Dim mcnn As ADODB.Connection
Dim mrs As New ADODB.Recordset
Dim uCustomClass As CustomClass
On Error GoTo 0
'set Find to false to catch any errors
Find = False
'checks for an active connection and then..
Set mCol = Nothing
Set mCol = New Collection
With mrs
.Open AN_SQL_SELECT_STATEMENT , mcnn, adOpenForwardOnly, adLockOptimistic
While Not .EOF
Set uCustomClass = New CustomClass
Set uCustomClass.Connection = mcnn
uCustomClass.CustomerName = NullToEquiv(.Fields("customer_name").Value,NULL_STRING)
uCustomClass.NumberOfOrders = NullToEquiv(.Fields("num_of_orders").Value, NULL_LONG)
uCustomClass.FavoriteColour = NullToEquiv(.Fields("favorite_colour").Value, NULL_STRING)
'Cache orginal values in case the keys change
uCustomClass.CacheOriginalValues
'add to collection
mCol.Add uCustomClass
.MoveNext
Wend
Now the result of this in run time is that the uCustomClass tree structure looks like:
-uCustomClass
+connection
count
+ mcnn
-mCol
+Item1
+Item2
+Item3
+mrs
mvarChangedCount
+NewEnum
It's all good bar I'm not getting Item1, Item2 and Item3 directly under the uCustomClass but only in mCol. I've what appears to be the exact same code running elsewhere for a different custom class and I'm getting what I want e.g.
-uCustomClassThatWorks
+connection
count
+ mcnn
-mCol
+Item1
+Item2
+Item3
+mrs
mvarChangedCount
+NewEnum
+Item1
+Item2
+Item3
Any ideas where the problem might be?
Not sure how uCustomClass would ever get those items added. Is there some missing code or something?
One point worth making is that collections can't have the same keys more than once, which would explain why they are able to be added in one area, but not able to be added again. There might be something that is even trimming strings or something that would aggravate the situation. So just make sure your keys are unique.

ArcPad - VBscript - Autopopulate attributes

I am using the following script to grab parcel and address information from one layer to fill the attribute table of a newly created feature.
There is no returned error, but the problem I am having is that there seems to be the wrong information stuck in the memory of recordselect function. No matter where I place a point it gives the same parcel # and address. Or maybe it isn’t actually be performing the IF function properly.
Sub Address
Dim rsCurrentXY
Set rsCurrentXY = Map.Layers("Violations").records
rsCurrentXY.movelast
Dim objXYShape
Set objXYShape = rsCurrentXY.Fields.Shape
Dim pControls
Set pControls= Application.Map.selectionlayer.Forms("EDITFORM").Pages(“PAGE1”).Controls
Dim rsGrid
' Find corresponding map page to the valve point
Set rsGrid = Map.Layers("ACPA_parcels").records
rsGrid.movefirst
Do While Not rsGrid.eof
If rsGrid.fields.shape.Ispointin(objXYShape) Then
pControls("txtAddress").value = rsGrid.Fields("ADD1").Value
Exit Do
End If
rsGrid.Movenext
Loop
' Clean Up
Set rsCurrentXY = Nothing
Set objXYShape = Nothing
Set rsGrid = Nothing
End Sub
(I have another subroutine called "PIN" that would do the exact same thing.)
I have them called when their respective edit boxes in the custom form are activated by the inspector.
Thanks for the help,
Robert
Accessing the EDITFORM via Application.Map.selectionlayer.Forms("EDITFORM") will be problematic. Whenever working with controls on an EDITFORM you should using ThisEvent.Object to discover all your objects. For example, if your event handler is Page_OnLoad then ThisEvent.Object will refer to your current page. You should have code like this:
Dim pPage1
Set pPage1 = ThisEvent.Object
Dim pControls
Set pControls = pPage1.Controls

Why does recordset.RecordCount equal 1 but recordset.EOF and recordset.BOF both equal True

I have a very simple query that only returns one record. When I try to get the value out of the only column in the only record, I get "Either BOF or EOF is True, or the current record has been deleted. Requested operation requires a current record." What's going on here? The code that is causing the error doesn't even execute if RecordCount is 0 and I have verified that the recordset does in fact contain a record.
Code is below. Error is thrown when trying to set strDN. It's so dead simple but I can't figure out where I'm going wrong.
EDITED TO INCLUDE COMMAND
<LDAP://DC=something,DC=com>;(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(employeeID=01234567));distinguishedName;subtree
Set adoRecordset = adoCommand.Execute
If adoRecordset.RecordCount > 0 Then
strDN = adoRecordset.Fields("distinguishedName").Value
Set objUser = GetObject("LDAP://" & strDN)
objGroup.add(objUser.ADsPath)
End if
The recordcount property leaves the cursor at the end of the recordset, so you cannot then obtain the record (eof=true), you must movefirst. Use a different cursor type, because the default cursor type is forward only:
'' Assign cursorType that allows forward and backward movement.
adoRecordset.cursorType = 3 ''adOpenStatic
See https://www.w3schools.com/asp/prop_rs_cursortype.asp
I use
If Not adoRecordset.EOF And Not adoRecordset.BOF Then
...
End If
For This Scenario
Try
Set adoRecordset = adoCommand.Execute
If adoRecordset.RecordCount > 0 Then
adoRecordset.MoveFirst 'Move to the first record
strDN = adoRecordset.Fields("distinguishedName").Value
Set objUser = GetObject("LDAP://" & strDN)
objGroup.add(objUser.ADsPath)
End if
-EDIT-
Have a look at the following link. There are some causes listed, and solutions for most of them:
http://classicasp.aspfaq.com/general/why-do-i-get-bof-or-eof-errors.html
[I was wrong about this - thanks, Dave] I believe you need to call adoRecordset.MoveNext (or whatever the call is) before attempting to get the value of a field in the recordset.
Calling adoRecordSet.Requery() after RecordCount request can also help in this situation, if your query isn't that complex to execute it the second time.

VB6 / Crystal Report 8.5 error: A string is required here

I recently inherited an old visual basic 6/ crystal reports project which connects to a sql server database. The error message I get (Error# -2147191803 A String is required here) when I attempt to run the project seems to be narrowed down to the .Printout command in the following code:
'Login to database
Set Tables = Report.Database.Tables
Set Table = Tables.Item(1)
Table.SetLogOnInfo ConnName, DBName, user, pass
DomainName = CStr(selected)
'Set parameter Fields
'Declare parameter holders
Set ParamDefs = Report.ParameterFields
'Store parameter objects
For Each ParamDef In ParamDefs
With ParamDef
MsgBox("DomainName : " + DomainName)
Select Case .ParameterFieldName
Case "Company Name"
.SetCurrentValue DomainName
End Select
Select Case .Name
Case "{?Company Name}"
.SetCurrentValue DomainName
End Select
'Flag to see what is assigned to Current value
MsgBox("paramdef: " + ParamDef.Value)
End With
Next
Report.EnableParameterPrompting = False
Screen.MousePointer = vbHourglass
'CRViewer1.ReportSource = Report
'CRViewer1.ViewReport
test = 1
**Report.PrintOut**
test = test + 3
currenttime = Str(Now)
currenttime = Replace(currenttime, "/", "-")
currenttime = Replace(currenttime, ":", "-")
DomainName = Replace(DomainName, ".", "")
startName = mPath + "\crysta~1.pdf"
endName = mPath + "\" + DomainName + "\" + DomainName + " " + currenttime + ".pdf"
rc = MsgBox("Wait for PDF job to finish", vbInformation, "H/W Report")
Name startName As endName
Screen.MousePointer = vbDefault
End If
During the run, the form shows up, the ParamDef variable sets the "company name" and when it gets to the Report.PrintOut line which prompts to print, it throws the error. I'm guessing the crystal report isn't receiving the "Company Name" to properly run the crystal report. Does any one know how to diagnose this...either on the vb6 or crystal reports side to determine what I'm missing here?
UPDATE:
inserted CStr(selected) to force DomainName to be a string
inserted msgboxes into the for loop above and below the .setcurrentvalue line
inserted Case "{?Company Name}" statement to see if that helps setting the value
tried .AddCurrentValue and .SetCurrentValue functions as suggested by other forum websites
ruled out that it was my development environement..loaded it on another machine with the exact same vb6 crystal reports 8.5 running on winxp prof sp2 and the same errors come up.
and when I run the MsgBox(ParamDef.Value) and it also turns up blank with the same missing string error. I also can't find any documentation on the craxdrt.ParameterFieldDefinition class to see what other hidden functions are available. When I see the list of methods and property variables, it doesn't list SetCurrentValue as one of the functions.
Any ideas on this?
What is the value of your selected variable?
Table.SetLogOnInfo ConnName, DBName, user, pass
DomainName = selected
'Set parameter Fields
If it is not a string, then that might be the problem. Crystal expects a string variable and when it doesn't receive what it expects, it throws errors.
selected is a string variable input taken from a form with a drop down select box. I previously put a message box there to ensure there the variable is passing through right before the Report.Printout and it does come up. DomainName variable is also declared as a string type.
Here's how I set my parameters in Crystal (that came with .NET -- don't know if it helps you).
Dim dv As New ParameterDiscreteValue
dv.Value = showphone
rpt.ParameterFields("showphone").CurrentValues.Add(dv)
This can happen in crystal reports 8.5 if you changed the length of a string column you use in your report so that it exceeds 255 bytes. This can also happen if you change the column type from varchar to nvarchar (double byte string!)
The reason for this is that crystal reports 8.5 treats all strings longer than 255 bytes as memo fields.
I would suggest youe upgrade to crystal reports XI - the API has not changed that much.
From my point of view you should get the same error message if you open the report in the Crystal Reports Designer and switch to preview mode. The Designer should also show you a message with the exact location of the problem, e.g. the field which can not be treated as a string.
The problem is not that a field longer than 255 bytes cannot be printed. The problem is that a field longer than 255 bytes cannot be used in a formula, as a sort criteria ...
Here is a live example of setting the parameters that we use:
For Each CRXParamDef In CrystalReport.ParameterFields
Select Case CRXParamDef.ParameterFieldName
Case "#start"
CRXParamDef.AddCurrentValue CDate("1/18/2002 12:00:00AM")
Case "#end"
CRXParamDef.AddCurrentValue Now
End Select
Next
This is actually a sample written in VBScript for printing Crystal 8.5 reports, but the syntax is the same for VB6

Resources