Passing scripting.dictionary[] by ref to Function - vbscript

I am working on small VBScript and trying to create scripting.dictionary[]. I have to pass that array of dictionary to a function by ref. I got that function through compiled library. the function definition is below.
public string Update(string name, ref Scripting.Dictionary[] Data, string sRecordId = "")
My lines of code is here
Set objQWS = CreateObject("Dll")
Set X = PassDictionary
objQWS.Update "Name", x, ""
MsgBox "Additional Info Sent"
Function PassDictionary()
Dim objDic
Set objDic = CreateObject("Scripting.Dictionary")
objDic.Add "id", 1
objDic.Add "name", "a"
objDic.Add "extd_price", "b"
objDic.Add "sales_rep", "c"
objDic.Add "opportunity_id", "d"
Set PassDictionary = objDic
End Function
The problematic area is the Update function.
Every time I run the code, on Update function it give me the error "type mismatch". can anybody tell me how can I make that thing working?

You're passing a single dictionary, not an array of dictionaries. Try something like
Set x = PassDictionary
arr = Array(x)
objQWS.Update "Name", arr, ""
Not sure if it'll work, though, since VBScript doesn't really know types, so the array will have the type Variant().
Another thing you could try is to change the type of the parameter from Scripting.Dictionary[] to Scripting.Dictionary, since you're only passing a single dictionary anyway.

Related

Is there a faster way to get file metadata than by using the shell COM component?

Reading various answers here and elsewhere, I pieced together this bit to get the file metadata that I need:
Public Class windows_metadata_helper
Public Shared shell As New Shell32.Shell
Public Shared indices_of_interest As New Dictionary(Of Integer, String)
Public Shared path_index As Integer
Shared Sub New()
'snipped long piece code for figuring out the indices of the attributes that I need, they are stored in indices_of_interest, for example 0:Name
End Sub
Public Shared Function get_interesting_data(path) As Dictionary(Of String, String)
Dim fi As New IO.FileInfo(path)
Dim f_dir = shell.NameSpace(fi.DirectoryName)
Dim data As New Dictionary(Of String, String)
For Each item In f_dir.Items()
If f_dir.GetDetailsOf(item, path_index) = fi.FullName Then
For Each kvp In indices_of_interest
Dim val = f_dir.GetDetailsOf(item, kvp.Key)
If Not String.IsNullOrEmpty(val) Then data.Add(kvp.Value, val)
Next
Exit For
End If
Next
Return data
End Function
End Class
Its not the most efficient code in the world, namely getting the path attribute of each file in the directory to identify the file I'm actually interested in. Optimizing this to only read the path attribute of each file once makes it around 50% faster (tested by letting it take the first file it finds whether its the right one or not) but regardless, its far slower than expected.
It needs to fetch 24 attributes from each file and it needs to find around 20k files from within ~100k, currently this takes an entire hour.
Profiling tells me that CPU is the bottleneck and whatever is taking up the cycles I can't see since its 99% inside the Shell32.Folder.GetDetailsOf method.
Is there a faster way to get the metadata? Answer doesn't have to be vb or .net specific.
Since you are seeking maximum speed, I suggest that you enable Option Strict for your code and make the necessary modifications that will be suggested by the IDE. This will eliminate unnecessary type conversions.
For instance,
Public Shared Function get_interesting_data(path) As Dictionary(Of String, String)
should be:
Public Shared Function get_interesting_data(path As String) As Dictionary(Of String, String)
Instead of enumerating the Shell32.Folder.Items collection, use the Shell32.Folder.ParseName Method to directly retrieve a FolderItem object. This object can be cast to a Shell32.ShellFolderItem that will allow using the ShellFolderItem.ExtendedProperty method.
There are two ways to specify a property. The first is to assign the
property's well-known name, such as "Author" or "Date", to sPropName.
However, each property is a member of a Component Object Model (COM)
property set and can also be identified by specifying its format ID
(FMTID) and property ID (PID). An FMTID is a GUID that identifies the
property set, and a PID is an integer that identifies a particular
property within the property set.
Specifying a property by its FMTID/PID values is usually more
efficient than using its name. To use a property's FMTID/PID values
with ExtendedProperty, they must be combined into an SCID. An SCID is
a string that contains the FMTID/PID values in the form "FMTID**PID",
where the FMTID is the string form of the property set's GUID. For
example, the SCID of the summary information property set's author
property is "{F29F85E0-4FF9-1068-AB91-08002B27B3D9} 4".
Many FMTID/PID values can be found under links presented at Windows Properties.
You can find the full property table here (scroll down).
Putting this together for some selected properties:
Public Shared Function get_interesting_data(path As String) As Dictionary(Of String, String)
Dim fi As New IO.FileInfo(path)
Dim f_dir As Shell32.Folder = shell.NameSpace(fi.DirectoryName)
' instead of enumerating f_dir.Items to find the file of interest
' directly retrieve the item reference
Dim item As Shell32.ShellFolderItem = DirectCast(f_dir.ParseName(fi.Name), Shell32.ShellFolderItem)
Dim scid_Bitrate As String = "{64440490-4C8B-11D1-8B70-080036B11A03} 4" ' Audio: System.Audio.EncodingBitrate
Dim scid_Title As String = "{F29F85E0 - 4.0FF9-1068-AB91-08002B27B3D9} 2" ' Core: System.Title
Dim scid_Created As String = "{B725F130-47EF-101A-A5F1-02608C9EEBAC} 15" ' Core: System.DateCreated
Dim scid_Copyright As String = "{64440492-4C8B-11D1-8B70-080036B11A03} 11" ' Core: System.Copyright
Dim scid_Publisher As String = "{64440492-4C8B-11D1-8B70-080036B11A03} 30" ' Media: System.Media.Publisher
Dim scid_FullDetails As String = "{C9944A21-A406-48FE-8225-AEC7E24C211B} 2" ' PropList: System.PropList.FullDetails
Dim bitrate As Object = item.ExtendedProperty(scid_Bitrate)
Dim title As Object = item.ExtendedProperty(scid_Title)
Dim created As Object = item.ExtendedProperty(scid_Created)
Dim copyright As Object = item.ExtendedProperty(scid_Copyright)
Dim publisher As Object = item.ExtendedProperty(scid_Publisher)
Dim fullDetails As Object = item.ExtendedProperty(scid_FullDetails)
Dim data As New Dictionary(Of String, String)
' save the retrieved properties
Return data
End Function
I do not know if this technique of retrieving the properties is faster than you have currently using GetDetailsOf, but the other changes should make some improvement.

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

Microsoft VBScript runtime error '800a01a8' : object required

Hi i have an ASP page that call function with 2 parameters
when i call the function from the asp page i am getting this error
Microsoft VBScript runtime error '800a01a8'
Object required: 'AllPerInfo4xfm(...)'
my code is
set GetAllInv = new GetFunction
set MyOrsk = GetAllInv.AllPerInfo4xfm(ssgr,nat)
my function is
Public Function AllPerInfo4xfm(ssgr,nat)
dim sdir,sdir2,ssec,tlen,ssec2
tlen=len(ssgr)
sql ="Select * from Personal"
myors2.Open SQl,oConn,1,1
set Allperinfo4xf = myors2
end function
did i miss something
please advice
Assuming that AllPerInfo4xfm() does not return an object, loose the Set in
set MyOrsk = GetAllInv.AllPerInfo4xfm(ssgr,nat)
=>
MyOrsk = GetAllInv.AllPerInfo4xfm(ssgr,nat)
Update wrt comment:
If AllPerInfo4xfm() should return a recordset, make sure the function contains a line
Set AllPerInfo4xfm = objRecordset
(replace objRecordset with your variable name; now, of course, the Set in the assignment to MyOrsk is needed)
Update wrt OT's revision:
Given the revised code, both GetAllInv and myors2 should be checked. Are they valid objects when the line is executed?
cf. food for thought

QTP handling Null values with public functions

I am trying to write a QTP Script which works as follows
* takes a column from table checks if it is null
if yes
it adds that column name in a variable .
Later that column name will be used to display to user that all such fields are left blank .
Something like this:
Set rsRecordset1 = dbConnection.Execute("select formcd,sndrpstlcd,recppstlcd,sndrcntrycd, from test_data where trk in ('"&tin&"')")
If rsRecordset1.EOF = false Then
Blank_field="blank_fields->"
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (typcd,Blank_field)
packaging = rsRecordset1("packaging").value
typcd="packaging"
Call validatenull (typcd,Blank_field)
......
Public function validatenull (typcd,Blank_field)
If (isnull(typcd) )Then
Blank_field = Blank_field & " " & typcd &", "
End If
End Function
Value of blank_Field is expected to catch values as "blank_fields->Form_id,packaging (Considering Form_id, Packaging passes Null values) {It shouldnt add values which are not Null to blank_fields}
In simpler words
ss = Null
call nnn(ss)
Public function nnn(ss)
If isnull(ss) Then
msgbox("yes")
End If
End Function
Has Error that msgbox does not populates But,
ss= Null
nnn(ss)
If isnull(ss) Then
msgbox("yes")
End If
Populates Msgbox as Yes
But I want Case 1 to be working and I do not want to add any more variables to the function name.
IF By making an Array we can do it, please suggest .
It appears your function works fine, but you are passing the wrong values. From your code snippet:
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (typcd,Blank_field)
When you call 'validatenull', you are passing the variable 'typecd'. On the previous line, you populate this variable with a string, so it will never be null. It appears what you intended to pass was the variable 'formcd'. Your second call to 'validatenull' does the same thing. Here is your first call modified to use the other variable.
formcd = rsRecordset1("formcd").value
typcd="formcd"
Call validatenull (formcd,Blank_field)

Adding both text and an ID value to a VB6 combobox

I am currently trying to add to my VB6 combobox using the AddItem method. This works, however, I want to display text in the drop down but I need to pass the ID of that text.
Is there a way to accomplish this by using the AddItem method?
It can't be done in the AddItem method but it's fairly easy to do it immediately after, using the NewIndex property, as long as the ID is a numeric value:
With Combo1
For i = 16 To 34
.AddItem "Item " & i
.ItemData(.NewIndex) = i
Next
End With
As the ID was not numeric I didn't use the solution above.
I had to create a type that had a "desc" and an "cod" and then create an array of that type.
I then used the ListIndex of the drop down (populated by the array) to get the element value which contained the id.
Private Type T_arrType
cod As String
dsc As String
End Type
dim x as integer
x = cbo.listIndex
msgbox(strArr(x).cod)
msgbox(strArr(x).dsc)

Resources