How to pass an array with fixed length strings to a function - vb6

I am trying to pass an array of fixed length strings to a function. However, the function will not know the size of the strings. The parameter should take any size strings. How would I go about this? Here is my code:
Public Type myRecord
names(15) As String * 250
End Type
Function def:
Function HasQuotes(textArr() As String) As String
End Function
Usage:
HasQuotes(rowRec.names)
where rowRec is a MyRecord.
When I run this code I get the following error Type Mismatch: array or user defined type expected. This is because the parameter is not defined as textArr() As String * 250. How can I make the parameter accept any string length?

You Have to follow Proper syntax you can Try Following updated Code
Private Type myRecord
names(15) As String * 250
End Type
Private Sub Command1_Click()
Dim rowRec As myRecord
rowRec.names(0) = ("Vaibhav")
Dim v As String
v = HasQuotes(rowRec.names)
End Sub
Function HasQuotes(ByRef textArr() As String * 250) As String
MsgBox textArr(0)
End Function

You are going to have trouble passing an array of fixed-length strings of any length. One simple solution is to convert them to an array of variable-length strings:
Private Sub Test()
Dim rowRec As myRecord
Dim names(15) As String
Dim i As Integer
Dim s As String
rowRec.names(0) = "Brian"
rowRec.names(15) = "Stafford"
'move the data to an array of variable-length strings
For i = 0 To 15
names(i) = rowRec.names(i)
Next
s = HasQuotes(names)
'move the data back to the original array if needed
For i = 0 To 15
rowRec.names(i) = names(i)
Next
End Sub

Related

Convert a value with a regex to a real value

I have a huge file containing values with a regex in it, like this:
LGP0041_\d{4}\.dta
objd135a_\S{3}.txt
Now I need to convert these to a valid example value, like this:
LGP0041_1234.dta
objd135a_abc.txt
I know of the RegExp object to check if there is a match, but is there also a way to create valid values?
A regular grammar can be used to recognize or produce words of its language, but the VBScript regexp engine does not implement producing. So you have to roll your own.
Your sample does not contain contain regular patterns. \S can't mean 'non-whitespace' because you won't like characters illegal in a file name and a representative sample of file names should contain elements with spaces. The fact that the first sample escapes the extension dot and the second one doesn't makes me think that your syntax specs aren't really thought out. If you come up with a (regular) grammar of your inputs, I'm willing to give your problem further thought.
Some code to base the thinking on:
Option Explicit
Function rndInt(lowerbound, upperbound)
rndInt = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
End Function
Sub shuffleAD(aX)
' Durstenfeld's Permutation Algorithm
Dim J, K, Temp
For J = UBound(aX) To 1 Step -1
K = Int((J + 1) * Rnd) ' random number 0 - J
Temp = aX(J)
aX(J) = aX(K)
aX(K) = Temp
Next
End Sub ' shuffleAD
Class cRGen
Private m_
Public Function init(s)
Set init = Me
ReDim m_(Len(s) - 1)
Dim i
For i = 0 To UBound(m_)
m_(i) = Mid(s, i + 1, 1)
Next
End Function
Public Function getNext(mi, ma)
shuffleAD m_
getNext = Mid(Join(m_, ""), 1, rndInt(mi, ma))
End Function
End Class
Dim goRpl : Set goRpl = Nothing
Function magic(m, w, mi, ma, p, src)
If IsEmpty(ma) Then ma = mi
magic = goRpl.m_dicGens(w).getNext(mi, ma)
End Function
Class cRpl
Private m_fRpl
Private m_r
Public m_dicGens
Private Sub Class_Initialize()
Set m_fRpl = GetRef("magic")
Set m_r = New RegExp
m_r.Pattern = "\\(\w){(\d+)(?:,(\d+))?}"
Set m_dicGens = CreateObject("Scripting.Dictionary")
Set m_dicGens("d") = New cRGen.init("0123456789")
Set m_dicGens("S") = New cRGen.init("abcdefghij")
End Sub
Public Function rpl(s)
Set goRpl = me
rpl = m_r.Replace(s, m_fRpl)
End Function
End Class
Randomize
Dim aTests : aTests = Array( _
"LGP0041_\d{4}.dta" _
, "objd135a_\S{3}.txt" _
, "x_\S{3,8}.txt" _
)
Dim oRpl : Set oRpl = New cRpl
Dim sTest
For Each sTest In aTests
WScript.Echo sTest, "=>", oRpl.rpl(sTest)
Next
output:
cscript 28936688.vbs
LGP0041_\d{4}.dta => LGP0041_4317.dta
objd135a_\S{3}.txt => objd135a_cea.txt
x_\S{3,8}.txt => x_jgcfidh.txt
cscript 28936688.vbs
LGP0041_\d{4}.dta => LGP0041_8054.dta
objd135a_\S{3}.txt => objd135a_eci.txt
x_\S{3,8}.txt => x_ahfgd.txt
This should at least identify the needed components:
generators that deliver strings of specific character sets
a (sorry: global) replace function that maps 'type letters' to generators, handles 'width specs', and build the output
a regular pattern to parse the specs from your inputs

I'm trying to pass a parameter using this

Option Explicit
Public Sub Main(): If Con.Initialize = conLaunchExplorer Then Con.Visible = False
Dim strParameters As String
Dim readL As String
strParameters = Split(Command$, "/")
Con.WriteLine strParamers
readL = Con.ReadLine
End Sub
This is code right now as you can see I'm trying to split the strParameters but the error says mismatch please help me.
When Splitting a string, the data is placed in an array, and according to your declaration strParameters is a simple string. How would the different parts fit in one string? You just need to change your declaration as follows;
Dim strParameters() As String
Assuming that your Command$ is correctly declared as string, with delimiters "/"

Syntax error when passing an array to a method

I have created and array which will store the value of the inputbox, it is saying i have a syntax error and i am unsure how to fix it.
I have used parameter passing which i will display below also
Dim name() As String
For counter = 1 To 5
Call enter_questionnaire_data(name()) '2.0
Next
End sub
2nd sub-routine
Private Sub enter_questionnaire_data(ByRef name())
name() = InputBox("Enter the party name")
why do you have name as a String array?
you just need to declare
Dim name As String
for allowing name to store a String
also you cannot assign values to array members like this
name() = InputBox("Enter the party name")
you need to specify the index also
EDIT:
if you want string array to store the names, then
declare a static array of sufficient length
Dim name(10) As String
and use:
name(index) = InputBox("Enter the party name")
index = index+1;
where the index is incremented after every input till 10
(using dynamic array would be a bit complicated for you right now , so i am omitting dynamic array from discussion)
Use name without brackets
Dim name As String
and in other method
Private Sub enter_questionnaire_data(ByRef name)
name = InputBox("Enter the party name")
About your program:
Dim name As String <---Without () you can use this for array
For counter = 1 To 5
Call enter_questionnaire_data(name as string)<--- can you insert variable/tipe
Next
End sub
Private Sub enter_questionnaire_data(name as string)
name = InputBox("Enter the party name")

I want to read the last 400 lines from a txt file

I know how to do it in VB.Net but not an idea in vb6.
What I what to achieve is to avoid reading the whole file.
Is that possible?
You could open the file using Random access. Work your way backward a byte at a time, counting the number of carriage return line feed character pairs. Store each line in an array, or something similar, and when you've read your 400 lines, stop.
Cometbill has a good answer.
To open file for Random access:
Open filename For Random Access Read As #filenumber Len = reclength
To get the length of the file in Bytes:
FileLen(ByVal PathName As String) As Long
To read from Random access file:
Get [#]filenumber,<[recnumber]>,<varname>
IMPORTANT: the <varname> from the Get function must be a fixed length string Dim varname as String * 1, otherwise it will error out with Bad record length (Error 59) if the variable is declared as a variable length string like this Dim varname as String
EDIT:
Just wanted to point out that in Dim varname as String * 1 you are defining a fixed length string and the length is 1. This is if you wish to use the read-1-byte-backwards approach. If your file has fixed length records, there is no need to go 1 byte at a time, you can read a record at a time (don't forget to add 2 bytes for carriage return and new line feed). In the latter case, you would define Dim varname as String * X where X is the record length + 2. Then a simple loop going backwards 400 times or untill reaching the beginning of the file.
The following is my take on this. This is more efficient than the previous two answers if you have a very large file, since we don't have to store the entire file in memory.
Option Explicit
Private Sub Command_Click()
Dim asLines() As String
asLines() = LoadLastLinesInFile("C:\Program Files (x86)\VMware\VMware Workstation\open_source_licenses.txt", 400)
End Sub
Private Function LoadLastLinesInFile(ByRef the_sFileName As String, ByVal the_nLineCount As Long) As String()
Dim nFileNo As Integer
Dim asLines() As String
Dim asLinesCopy() As String
Dim bBufferWrapped As Boolean
Dim nLineNo As Long
Dim nLastLineNo As Long
Dim nNewLineNo As Long
Dim nErrNumber As Long
Dim sErrSource As String
Dim sErrDescription As String
On Error GoTo ErrorHandler
nFileNo = FreeFile
Open the_sFileName For Input As #nFileNo
On Error GoTo ErrorHandler_FileOpened
' Size our buffer to the number of specified lines.
ReDim asLines(0 To the_nLineCount - 1)
nLineNo = 0
' Read all lines until the end of the file.
Do Until EOF(nFileNo)
Line Input #nFileNo, asLines(nLineNo)
nLineNo = nLineNo + 1
' Check to see whether we have got to the end of the string array.
If nLineNo = the_nLineCount Then
' In which case, flag that we did so, and wrap back to the beginning.
bBufferWrapped = True
nLineNo = 0
End If
Loop
Close nFileNo
On Error GoTo ErrorHandler
' Were there more lines than we had array space?
If bBufferWrapped Then
' Create a new string array, and copy the bottom section of the previous array into it, followed
' by the top of the previous array.
ReDim asLinesCopy(0 To the_nLineCount - 1)
nLastLineNo = nLineNo
nNewLineNo = 0
For nLineNo = nLastLineNo + 1 To the_nLineCount - 1
asLinesCopy(nNewLineNo) = asLines(nLineNo)
nNewLineNo = nNewLineNo + 1
Next nLineNo
For nLineNo = 0 To nLastLineNo
asLinesCopy(nNewLineNo) = asLines(nLineNo)
nNewLineNo = nNewLineNo + 1
Next nLineNo
' Return the new array.
LoadLastLinesInFile = asLinesCopy()
Else
' Simply resize down the array, and return it.
ReDim Preserve asLines(0 To nLineNo)
LoadLastLinesInFile = asLines()
End If
Exit Function
ErrorHandler_FileOpened:
' If an error occurred whilst reading the file, we must ensure that the file is closed
' before reraising the error. We have to backup and restore the error object.
nErrNumber = Err.Number
sErrSource = Err.Source
sErrDescription = Err.Description
Close #nFileNo
Err.Raise nErrNumber, sErrSource, sErrDescription
ErrorHandler:
Err.Raise Err.Number, Err.Source, Err.Description
End Function

How to get the value from method in Visual Basic 6

The code below returns error after the return statement
Private Sub Command1_Click()
Dim str As String
str = display("test")
MsgBox (str)
End Sub
Public Function display(s As String) As String
s = "updated"
Return s
End Function
Any ideas why?
Change display function. The difference is that in vb6 functions return a value not with return, but with it's name(in this case display), like below.
Public Function display(s As String) As String
s = "updated"
display = s
End Function

Resources