How to solve "object converted to string" error in B4A - vb4android

Sub Process_Globals
'These global variables will be declared once when the application starts.
'These variables can be accessed from all modules.
Type DBResult (Tag As Object, **Columns As Map**, Rows As List)
Type DBCommand (Name As String, Parameters() As Object)
Private const rdcLink As String = "http://192.168.8.100:17178/rdc"
End Sub
This is the methods for process globals . Here columns As Map is initialized .
However the line bolded in the below code gives an error as , "Object converted to String. This is probably a programming mistake. (warning #7)"
Sub GetRecord
Dim req As DBRequestManager = CreateRequest
Dim cmd As DBCommand = CreateCommand("selectAllNames", Null)
Wait For (req.ExecuteQuery(cmd, 0, Null)) JobDone(j As HttpJob)
If j.Success Then
req.HandleJobAsync(j, "req")
Wait For (req) req_Result(res As DBResult)
'work with result
'req.PrintTable(res)
***Log(res.Columns)***
ListViewListTable.Clear
For Each row() As Object In res.Rows
Dim oBitMap As Bitmap
Dim buffer() As Byte
buffer = row(res.Columns.Get("gambar"))
oBitMap = req.BytesToImage(buffer)
ListViewListTable.AddTwoLinesAndBitmap(row(1), "See more...", oBitMap)
Next
Else
Log("ERROR: " & j.ErrorMessage)
End If
j.Release
End Sub
So what should I do to remove the error?

If columns is a map? (which it looks to be?).
Then to display the columns you can use this:
For Each MyKey As String in res.Columns.Keys
log("Key name = " & MyKey)
log("Key value = " & res.Columns.Get(MyKey))
Next

Related

Accessing an object property from within another object that contains it

I'll try to explain it to the best of my ability with my limited knowledge...
I have a square matrix, same amount of rows and columns, i need to loop thru it and store the information of each cell in a certain way, i've done it previously with arrays and got everything working, but i'm trying to improve on my coding skills, and i've known for a while that objects are the way to go usually... this is my second attempt after quite a while of just not trying due to being defeated...
The thing is... I have 2 objects, one named Proveedor, this guy will have 3 properties:
Unidad Decisoria_Prov: a string
Responsable_Prov: a string
Requerimientos: an array of Vinculo objects
Private pedidos_() As Vinculo
Private ud_P As String
Private responsable_P As String
Option Explicit
Public Property Let Requerimientos(index As Integer, str As Vinculo)
If index > UBound(pedidos_) Then ReDim Preserve pedidos_(index)
If pedidos_(index) Is Nothing Then
Set pedidos_(index) = New Vinculo
End If
Set pedidos_(index) = str
End Property
Public Property Get Requerimientos(index As Integer) As Vinculo
If index > UBound(pedidos_) Then Requerimientos = "El indice del get esta fuera de rango": Exit Property
Requerimientos = pedidos_(index)
End Property
Public Property Let Unidad_Decisoria_Prov(str As String)
ud_P = str
End Property
Public Property Get Unidad_Decisoria_Prov() As String
Unidad_Decisoria_Prov = ud_P
End Property
Public Property Let Responsable_Prov(str As String)
responsable_P = str
End Property
Public Property Get Responsable_Prov() As String
Responsable_Prov = responsable_P
End Property
Private Sub class_initialize()
ReDim pedidos_(0)
End Sub
The other object is named Vinculo, this one has 3 properties:
Unidad Decisoria_C: a string
Responsable_C: a string
Requerimiento: a string
Private ud_ As String
Private responsable_ As String
Private requerimiento_ As String
Option Explicit
Public Property Let Unidad_Decisoria_C(str As String)
ud_ = str
End Property
Public Property Get Unidad_Decisoria_C() As String
Unidad_Decisoria_C = ud_
End Property
Public Property Let Responsable_C(str As String)
responsable_ = str
End Property
Public Property Get Responsable_C() As String
Responsable_C = responsable_
End Property
Public Property Let Requerimiento(str As String)
requerimiento_ = str
End Property
Public Property Get Requerimiento() As String
Requerimiento = requerimiento_
End Property
Once I have the objects working as intended i'll loop thru the matrix and do what i need to with the data, but before wasting time on that, i'm trying to test it with the following code:
Sub testing_2_objetosjuntos()
Dim mi_Prov As Proveedor
Dim un_vin As Vinculo
Set mi_Prov = New Proveedor
Set un_vin = New Vinculo
mi_Prov.Unidad_Decisoria_Prov = "tarea del proveedor 1"
mi_Prov.Responsable_Prov = "responsable de la tarea del proveedor 1"
un_vin.Unidad_Decisoria_C = "tarea del cliente 1"
un_vin.Responsable_C = "responsable de la tarea 1 del cliente"
un_vin.Requerimiento = "hace tal cosa"
mi_Prov.Requerimientos(0) = un_vin
Debug.Print mi_Prov.Requerimientos(0).Requerimiento
Debug.Print mi_Prov.Requerimientos(0).Responsable_C
End Sub
Up to the debug.print command everything works fine as far as i can tell...
watches up until the first debug.print line
however when i try to access the properties of the vinculo object stored in the first index of the Proveedor object i get a beautiful
Run-time error 91:
Object variable or With block variable not set
The actual line that gives me that error is the get property of Requerimientos in the Proveedor class.
This is probably a silly question but not only i can't understand why it breaks, i'm unable to apparently ask the question properly in google to not have to bother you guys...
I expected to read the string stored in the vinculo.Requerimiento property which is in the first index of the array of Requerimientos property of the Proveedor object.
The reason for your problem is easy to fix. As Vinculo is an object, you need to use the Set keyword in the Requerimientos-getter:
Public Property Get Requerimientos(index As Integer) As Vinculo
Set Requerimientos = pedidos_(index)
End Property
However, your error handling will fail: If index > UBound(pedidos_), you are assigning a String as return value which is not allowed (remember, your function returns an object of type Vinculo, not a String).
You should raise an error instead
Public Property Get Requerimientos(index As Integer) As Vinculo
Err.Raise vbObjectError + 1000, "El indice del get esta fuera de rango", "Sorry..."
Set Requerimientos = pedidos_(index)
End Property
And a hint: You had problems to identify the error of your test routine because the VBA runtime didn't halt on the line of error. This is because the default setting of the VBA debugger is "Break on unhandled errors" which doesn't include to break within a class module (hint: Userforms are also classes). Change this setting to "Break in class modules" to see the exact line where the error occurs.
Tools->Options->General

Class constructor confusion - wrong number of arguments or invalid property assignment

I'm having a class module with some data:
Private sharedFolders() As String
Public Property Let SetSharedFolders(val As String)
Dim i As Integer
sharedFolders = Array("folder one", "folder two")
i = UBound(sharedFolders)
i = UBound(sharedFolders)
ReDim Preserve sharedFolders(i)
sharedFolders(i) = CStr(val)
End Property
Property Get GetSharedFolders()
GetSharedFolders = sharedFolders()
End Property
And I want to add something to this property from other module like this:
Sub PrepareData()
Dim e
Dim s
Dim a(2) As String
Set e = New Entry
a(0) = "add one"
a(1) = "add two"
For Each s In a
e.SetSharedFolders (s) 'Here comes exception
Next
For Each s In e.GetSharedFolders
Debug.Print s
Next
End Sub
But I receive an "wrong number of arguments or invalid property assignment vba" exception... Can anyone assist?
Addendum
Thanks to #AJD and #Freeflow to pointing out a mistake and idea to make it easier. Decided to make as like below.
Class Module:
Private sharedFolders As New Collection
Public Property Let SetSharedFolders(val As String)
If sharedFolders.Count = 0 Then ' if empty fill with some preset data and add new item
sharedFolders.Add "folder 1"
sharedFolders.Add "folder 2"
sharedFolders.Add CStr(val)
Else
sharedFolders.Add CStr(val)
End If
End Property
Property Get GetSharedFolders() As Collection
Set GetSharedFolders = sharedFolders
End Property
and regular module:
Sub AddData()
Dim e As New Entry ' creating an instance of a class
Dim s As Variant ' variable to loop through collection
Dim a(1) As String 'some array with data to insert
a(0) = "add one"
a(1) = "add two"
For Each s In a
e.SetSharedFolders = s
Next
For Each s In e.GetSharedFolders
Debug.Print s
Next
End Sub
Initially I thought the problem lies in this code:
i = UBound(sharedFolders)
i = UBound(sharedFolders)
ReDim Preserve sharedFolders(i)
sharedFolders(i) = CStr(val)
i is set twice to the same value, and then the sharedFolders is reDimmed to the same value it was before! Also, there is some trickery happening with the use of ix within a 0-based array.
But the problem is most likely how you have declared your variables.
For Each s In a
e.SetSharedFolders (s) 'Here comes exception
Next
s is a Variant, and a is a Variant. At this point VBA is trying to guess how to handle a For Each loop with two Variants. And then the improper call is made. The correct syntax is:
e.SetSharedFolders s '<-- no parenthesis
There are plenty of posts on StackOverflow explaining how to call routines and what the impact of the evaluating parenthesis are!
However, at this point we are only assuming it is passing in a single element of the array - it could be passing the full array itself (albeit unlikely).
And the third factor -
Public Property Let SetSharedFolders(val As String)
The parameter val is being passed ByRef and should be passed ByVal. This also has unintended side effects as I found out (Type mismatch trying to set data in an object in a collection).
Public Property Let SetSharedFolders(ByVal val As String)
All in all you have the perfect storm of ambiguity driving to an unknown result.
The answer here is to strongly type your variables. This removes about two layers of ambiguity and areas where errors can happen. In addition, this will slightly improve code execution.
Another aspect is to understand when you should pass something ByVal and when to use the default (preferably explicitly) ByRef.
And a final gratuitous hint: Use a Collection instead of an Array. Your code you have implies a Collection will be more efficient and easier to manage.
Addendum
(thanks to #FreeFlow):
If the OP changes the definition of sharedfolders to Variant rather than String() then the array statement will work as expected.
The line e.SetSharedFolders (s) will work fine if it is changed to e.SetSharedFolders = s because the method SetSharedFolders is a Let Property not a Sub. There are other errors but these two changes will make the code run.

Exist function in dictionary doesn't work for an object as Key created in a class module

In my code, in need to store two value in my key to be able to do the analysis i require. And since I didn't want to store everything in an array, i decided to create an object with 2 parameters. But when i run the Exist function of the dictionary with that object "TwoInputs" as the type of Key, I always get that they Key doesn't exist. Can anyone help please?
I added "Option Compare Text" just in case but the exist still return False.
When I run the code line by line and force it to go the If "true" condition, a new Key is still created, don't know why.
This is the class module i created:
Private acc As Double
Private act As Variant
'Account property
Public Property Get Account() As Double
Account = acc
End Property
Public Property Let Account(Value As Double)
acc = Value
End Property
'Activity property
Public Property Get Activity() As Variant
Activity = act
End Property
Public Property Let Activity(Value As Variant)
act = Value
End Property
In a normal module i wrote a function to create a TwoInputs object based on two entries:
Public Function cTwoInputs(Account As Double, Activity As Variant) As TwoInputs
Set cTwoInputs = New TwoInputs
cTwoInputs.Account = Account
cTwoInputs.Activity = Activity
End Function
Then I create a sub where I want to add the 2 informations in a Key if they exist:
While dataSheet.Range("dataAgent").Offset(j, 0).Value <> "Project ID:" And dataSheet.Range("dataAgent").Offset(j, 0).Row <= lRow
If dataSheet.Range("dataAgent").Offset( j, 0).Value = "Activity ID:" Then
actName = dataSheet.Range("dataAgent").Offset(j, 1).Value
End If
If (dataSheet.Range("dataAgent").Offset(j, 0).Value = "XXXXX" Or dataSheet.Range("dataAgent").Offset(j, 0).Value = "") Then
KeyExist.Account = dataSheet.Range("dataAccount").Offset(j , 0).Value
KeyExist.Activity = actName
If dicBudget.Exists(KeyExist) Then
dicBudget(KeyExist) = dicBudget(KeyExist) + dataSheet.Range("dataBudget").Offset(j , 0).Value
Else
dicBudget.Add cTwoInputs(dataSheet.Range("dataAccount").Offset(j, 0).Value, actName), dataSheet.Range("dataBudget").Offset( j, 0).Value
End If
End If
j = j + 1
Wend
.Exists() method compares objects by their instances not by values of their fields.
So it's better to use primitive types like String, Integer, Double etc. as keys, and not to use custom object as a key. If you really need to use object-key for some purpose than you must be sure that you call .Exists() method on the same object you put to dictionary (e.g. by storing that key in a global variable).

Lotus Notes : Not able to access properties file in lotuscript

Hi friends i want to access the properties file from machine from the specified path. For java Agent i used Properties method and extracted the data from the properties file. but now i want it to be done in lotuscript. I tried using properties method but it didnt work so i thought to read properties with the below code.
'Dim ColFileName As String
'ColFileName="C:\abcd.properties"
Open ColFileName For Input As 1
Do While Not EOF(1)
Line Input #1,txt$
MsgBox "TEXT FILE:"+txt$
In properties file i have a written it as
col=start
where i want to get the property of the col using getProperty method in java same way for lotusscript.
I added the above code but it is not working. Can anyone tell what mistake i have committed.
In Options
%Include "lserr.lss" 'This is just a list of constants.
Add these functions somewhere:
%REM
Function fstreamOpenFile(sPath As String, bTruncate As Boolean, bConfirmExists As Boolean) As NotesStream
<dl>
<dt>sPath</dt><dd>Filepath of the file to be opened/created.</dd>
<dt>bTruncate</dt><dd>Boolean. True if file is for output and any existing file should be replaced rather than appended to.</dd>
<dt>bConfirmExists</dt><dd>Boolean. If True, and the opened file is empty, then an ErrFileNotFound error will be thrown.</dd>
</dl>
%END REM
Function fstreamOpenFile(sPath As String, bTruncate As Boolean, bConfirmExists As Boolean) As NotesStream
Dim session as New NotesSession Dim stream As NotesStream
Set stream = session.Createstream()
If Not stream.Open(sPath) Then Error ErrOpenFailed, {Could not open file at "} + sPath + {"}
If bConfirmExists And stream.Bytes = 0 Then Error ErrFileNotFound, {File at "} + sPath + {" is missing or empty.}
If bTruncate Then Call stream.Truncate()
Set fstreamOpenFile = stream
End Function
Function fsPropertyFileValue(sFilePath As String, sPropertyName As String, sDefaultValue As String) As String
On Error GoTo ErrorQuietly
Dim stream As NotesStream
Dim sLine As String
Dim sLeft As String
Dim iLeftLen As Integer
Set stream = fstreamOpenFile(sFilePath, False, True)
sLeft = sPropertyName + "="
iLeftLen = Len(sLeft)
Do
sLine = stream.Readtext
If Left(sLine, iLeftLen) = sLeft Then
fsPropertyFileValue = Right(sLine, Len(sLine) - iLeftLen)
Exit Function
End If
Loop Until stream.Iseos
ReturnDefault:
fsPropertyFileValue = sDefaultValue
Exit Function
ErrorQuietly:
Print Now, Error$
Resume ReturnDefault
End Function
(Notes: I have not tested/debugged fsPropertyFileValue. The html tags in the comment is because, when editing an agent or script library, the designer client will parse and display the HTML tags.)
Then you can use fsPropertyFileValue("C:\abcd.properties", "col", "start") to get the value of the col property within C:\abcd.properties and, if that fails, use "start".

Excel VBA: Adding objects to a collection within a class

I am trying to create a class (named ClassSection) that contains a collection (named DefectCollection). It needs a function to add items to that collection but I'm having trouble making it work. I get Error 91 "Object variable or with block variable not set."
I have looked at the other answers on here, which is what got me this far, but I don't understand what I'm missing.
Here is the class module code:
Public DefectCollection As Collection
Private Sub Class_Initialise()
Set DefectCollection = New Collection
End Sub
Public Function AddDefect(ByRef defect As CDefect)
DefectCollection.Add defect [<---- error 91]
End Function
And here is the code that calls the function: ('defect' is another class, which works fine - I want each 'ClassSection' to be able to hold an unlimited number of 'defects')
Dim SC As Collection
Dim section As ClassSection
Set SC = New Collection
Dim SurveyLength As Double
For Each defect In DC
SurveyLength = WorksheetFunction.Max(SurveyLength, defect.Pos, defect.EndPos)
Next defect
SurveyLength = Int(SurveyLength)
For i = 0 To numSurveys
For j = 0 To SurveyLength
Set section = New ClassSection
section.ID = CStr(j & "-" & dates(i))
SC.Add Item:=section, Key:=section.ID
Next j
Next i
Dim meterage As Double
For Each defect In DC
meterage = Int(defect.Pos)
Set section = SC.Item(meterage & "-" & defect.SurveyDate)
section.AddDefect defect
Next defect
Thanks!
You get the error because the DefectCollection is Nothing. This is due to the fact that you mispelled the initalization method:
Private Sub Class_Initialise() '<-- it's with "Z", not "S"
Hence, the initialization of the class is never called, the object remain Nothing by default and the method fails when trying to add an object to Nothing

Resources