I have some code that populates a SOAP request in VB.NET. I get the data from a SQL query and run through the objects members to populate each one. I'm trying to find a quick(ish) way to not provide the member when it is empty rather than checking each value before applying it. As the SQL data comes in from a pipe delimited file in the first place we never get NULL just empty cells which get sent in the SOAP request as "".
Is there a way to define an objects member using a variable rather than its literal name?
UpLB_request_Items.Spare8 = Convert.ToString(SourceDataSet.tables(0).Rows(i)(colSPARE8))
UpLB_request_Items.Spare9 = Convert.ToString(SourceDataSet.tables(0).Rows(i)(colSPARE9))
UpLB_request_Items.Spare10 = Convert.ToString(SourceDataSet.tables(0).Rows(i)(colSPARE10))
Call IterateObject(UpLB_request_Items)
So this populates each member with the value from the SQL data (SourceDataSet), then I could send the completed object down to a Sub to check each value before I actually send it to the webservice
Sub IterateObject(objName)
Dim CollName = ""
For Each m As System.Reflection.PropertyInfo In objName.GetType().GetProperties()
If m.CanRead Then
If m.PropertyType.Name = "String" Then
CollName = m.Name
Dim CollVal = CallByName(objName, CollName, CallType.Get)
If CollVal = "" Then
objName.CollName = Nothing 'this is the tricky bit
End If
End If
End If
Next
End Sub
The bit where it obviously breaks is objName.CollName = Nothing as it will then say that the object doesn't have a member called CollName and I'm not sure if there is a way to force the code to evaluate CollName to its value (e.g. SPARE8 rather than the string "CollName")
I went with this in the end
UpLB_request_Items.Spare4 = Strings.Replace(Convert.ToString(SourceDataSet.Tables(0).Rows(i)(colSPARE4)), "", Nothing)
I have saved written a text file and it currently reads:
"first","surname","pass"
I want to read the password column so the 3rd one and define that as a variable. Its basically for a login, if pass in text file matches the entered pass (from user).
I have searched for about an hour now and no luck. Could someone guide me to a correct path.
Thanks.
Simple example of reading a small file line by line and splitting each one into fields:
' get the values from the user somehow:
Dim first As String = "James"
Dim surname As String = "Bond"
Dim pass As String = "007"
Dim validated As Boolean = False ' assume wrong until proven otherwise
' check the file:
Dim fileName As String = "c:\some folder\path\somefile.txt"
Dim lines As New List(Of String)(System.IO.File.ReadAllLines(fileName))
For Each line As String In lines
Dim values() As String = line.Split(",")
If values.Length = 3 Then
If values(0).Trim(Chr(34)) = first AndAlso
values(1).Trim(Chr(34)) = surname AndAlso
values(2).Trim(Chr(34)) = pass Then
validated = True
Exit For
End If
End If
Next
' check the result
If validated Then
MessageBox.Show("Login Successful!")
Else
MessageBox.Show("Login Failed!")
End If
If this is a CSV file, as seems to be the case, then the easiest way to read it will be with the TextFieldParser class. The MSDN already provides an excellent example for how to use it to read a CSV file, so I won't bother reproducing it here.
I've looked for similar questions regarding this with no luck. I currently have working code that looks for a specific instance of string in the email body and subject. Upon finding this string, it has userform that takes it in another direction. My intentions are to have it run through the entire email and count how many times it finds this iteration and give that a callable variable for that userform(popup). Here is my code. It comes back with an error that says "InvalidCastException" so i'm guessing this is a conversion error. Any ideas? Thanks!
Ok so I added your comments together and came up with the following. I'm getting alot of errors, as the regex.Pattern I'm assuming doesn't exist. Any ideas? Also thank you for the literature.
Dim regEx ' Create variable.
Dim numfound As Integer
regEx = New RegExp ' Create a regular expression.
'Here it tells me that the regEx.Patter doesn't exist or Pattern is a member of the regex class
regEx.Pattern = "\*#{9}\*" ' Set pattern.
regEx.IgnoreCase = True ' Set case insensitivity.
regEx.Global = True ' Set global applicability.
If regEx.Execute(mailItem.Body) Then
' Getting a "not declared" runtime what should it be declared a Integer such as Dim numfound as Object
numfound = regEx.count
End If
Did some more digging and basically I'm back where I started with an InvalidCastException,
Conversion from string "111111111
123121233
" to type 'Long' is not valid.
Basically in the body of my test email I had those two strings of numbers and it can't convert them to a string to then run through the regexp iteration. Any ideas?
Dim sBody : sBody = (mailItem.Body) Or (mailItem.Subject) 'This is where is gives me the error
Dim Search : Search = New RegExp
Search.Global = True
Search.Pattern = "\*#{9}\*"
MsgBox(Search.Execute(sBody).Count, MsgBoxStyle.OkOnly)
To get you started, if you want to use a RegExp:
(1) Start your reading here and here
(2) Demo code to give you food for thought:
>> Dim sBody : sBody = "Three instances of ###: ### and a part of ####."
>> Dim Search : Set Search = New RegExp
>> Search.Global = True
>> Search.Pattern = "#{3,3}"
>> WScript.Echo Search.Execute(sBody).Count
>>
3
>>
The easiest way to do this would be just create an instance of RegEx and use it to parse the Item.Body.
Set Search = new RegExp
Search.IgnoreCase = True
Search.Global = True
Search.Pattern = "\*#{9}\*"
If Search.Test(Item.Body) Then
'will hold how many times it has been found
numFound = Search.Count
End If
Here is a link with a bit more information on RegExp http://msdn.microsoft.com/en-us/library/ms974570.aspx
I'm working with VBA. I wrote a user define function that takes a string, process it and return a cleaned string. I am not sure what is wrong with it. I am not able to call it and ask it to process my string and return it. I am thinking there are a mistake in the way I am defining or returning it.
Public Function ProcessString(input_string As String) As String
' The temp string used throughout the function
Dim temp_string As String
For i = 1 To Len(input_string)
temp_string = Mid(input_string, i, 1)
If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
return_string = return_string & temp_string
End If
Next i
return_string = Mid(return_string, 1, (Len(return_string) - 1))
ProcessString = return_string & ", "
End Function
And I use this function like this
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
Last name is a string variable, usually looks like this Lastname*****, and I am trying to remove all the stars behind it. Have it return Lastname without the stars.
I received Compile error: ByRef arugment type mismatch when I tried to run this. I am using Windows XP with Office 2003.
EDIT: I added the basic struction of the code I have, I have about 20 lines of the similar code. Doing the same thing for each field I need.
Private Sub CommandButton2_Click()
' In my original production code I have a chain of these
' Like this Dim last_name, first_name, street, apt, city, state, zip As String
Dim last_name As String
' I get the last name from a fixed position of my file. Because I am
' processing it from another source which I copied and pasted into excel
last_name = Mid(Range("A4").Value, 20, 13)
' Insert the data into the corresponding fields in the database worksheet
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
I suspect you haven't set up last_name properly in the caller.
With the statement Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
this will only work if last_name is a string, i.e.
Dim last_name as String
appears in the caller somewhere.
The reason for this is that VBA passes in variables by reference by default which means that the data types have to match exactly between caller and callee.
Two fixes:
1) Force ByVal -- Change your function to pass variable ByVal: Public Function ProcessString(ByVal input_string As String) As String, or
2) Dim varname -- put Dim last_name As String in the caller before you use it.
(1) works because for ByVal, a copy of input_string is taken when passing to the function which will coerce it into the correct data type. It also leads to better program stability since the function cannot modify the variable in the caller.
I don't know why, but it is very important to declare the variables separately if you want to pass variables (as variables) into other procedure or function.
For example there is a procedure which make some manipulation with data: based on ID returns Part Number and Quantity information. ID as constant value, other two arguments are variables.
Public Sub GetPNQty(ByVal ID As String, PartNumber As String, Quantity As Long)
the next main code gives me a "ByRef argument mismatch":
Sub KittingScan()
Dim BoxPN As String
Dim BoxQty, BoxKitQty As Long
Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty)
End sub
and the next one is working as well:
Sub KittingScan()
Dim BoxPN As String
Dim BoxQty As Long
Dim BoxKitQty As Long
Call GetPNQty(InputBox("Enter ID:"), BoxPN, BoxQty)
End sub
I changed a few things to work with Option Explicit, and the code ran fine against a cell containing "abc.123", which returned "abc.12,". There were no compile errors.
Option Explicit ' This is new
Public Function ProcessString(input_string As String) As String
' The temp string used throughout the function
Dim temp_string As String
Dim i As Integer ' This is new
Dim return_string As String ' This is new
For i = 1 To Len(input_string)
temp_string = Mid(input_string, i, 1)
If temp_string Like "[A-Z, a-z, 0-9, :, -]" Then
return_string = return_string & temp_string
End If
Next i
return_string = Mid(return_string, 1, (Len(return_string) - 1))
ProcessString = return_string & ", "
End Function
I'll suggest you post more of your relevant code (that calls this function). You've stated that last_name is a String, but it appears that may not be the case. Step through your code line by line and ensure that this is actually the case.
While looping through your string one character at a time is a viable method, there's no need. VBA has built-in functions for this kind of thing:
Public Function ProcessString(input_string As String) As String
ProcessString=Replace(input_string,"*","")
End Function
Something is wrong with that string try like this:
Worksheets(data_sheet).Range("C2").Value = ProcessString(CStr(last_name))
It looks like ByRef needs to know the size of the parameter. A declaration of
Dim last_name as string
doesn't specify the size of the string so it takes it as an error. Before using
Worksheets(data_sheet).Range("C2").Value = ProcessString(last_name)
The last_name has to be declared as
Dim last_name as string *10 ' size of string is up to you but must be a fix length
No need to change the function. Function doesn't take a fix length declaration.
For me the problem here was that I was declaring multiple variables in a row instead of separate rows.
For example, I was trying to pass i as an integer to my function.
Dim i,j as integer - gets me the error
Dim i as integer - doesn't get the error
I have an application which creates a list from items in a collection. Then for each item, I will add it to an empty string, then add a newline character to the end of it. So ideally my string will look something like:
List1\nList2\nList3\n
Once this string is generated, I send it back to be placed in a placeholder for a pdf. If I try this code in a simple console application, it prints everything on a newline. But in my real world situation, I have to print it to a pdf. The items only show up with spaces in between them and not newlines. How can can format my strings so that pdf recognizes the newline symbol rather than ignoring it?
Here is my code that generates the string with newlines.
Private Function ConcatPlacardNumbers(ByVal BusinessPlacardCollection As BusinessPlacardCollection) As String
Dim PlacardNumbersList As String = Nothing
Dim numberofBusinessPlacards As Long = BusinessPlacardCollection.LongCount()
For Each BusinessPlacard As BusinessPlacard In BusinessPlacardCollection
numberofBusinessPlacards = numberofBusinessPlacards - 1
PlacardNumbersList = String.Concat(PlacardNumbersList, BusinessPlacard.PlacardNumber)
If numberofBusinessPlacards <> 0 Then
PlacardNumbersList = String.Concat(PlacardNumbersList, Enviornment.newline)
End If
Next
Return PlacardNumbersList
End Function
Try to add \u2028 instead:
Private Function ConcatPlacardNumbers(ByVal BusinessPlacardCollection As _
BusinessPlacardCollection) As String
Dim PlacardNumbersList As New StringBuilder()
For Each BusinessPlacard As BusinessPlacard In BusinessPlacardCollection
PlacardNumbersList.Append(BusinessPlacard.PlacardNumber)
'PlacardNumbersList.Append(ChrW(8232)) '\u2028 line in decimal form
PlacardNumbersList.Append(ChrW(8233)) '\u2029 paragr. in decimal form
Next
Return PlacardNumbersList.ToString
End Function
For paragraphs use \u2029instead. Fore more details:
http://blogs.adobe.com/formfeed/2009/01/paragraph_breaks_in_plain_text.html
The answer will depend on the tool that is being used to produce the PDF. Since newline doesn't work, I would actually try \n. The other possibility is that the PDF generation code is not designed to emit multiple lines; you can only determine this by examining the generation code.
However, there is a significant performance issue that you should address in your code: you will be generating a lot of string objects using this code. You should change the design to use System.Text.StringBuilder, which will greatly improve the performance:
Private Function ConcatPlacardNumbers(ByVal BusinessPlacardCollection As BusinessPlacardCollection) As String
Dim PlacardNumbersList As New System.Text.StringBuilder(10000)
For Each BusinessPlacard As BusinessPlacard In BusinessPlacardCollection
If PlacardNumbersList.Length <> 0 Then
' This is equivalent to Environment.NewLine
'PlacardNumbersList.AppendLine()
' The attempt to use \n
PlacardNumbersList.Append("\n")
End If
PlacardNumbersList.Append(BusinessPlacard.PlacardNumber)
Next
Return PlacardNumbersList.ToString
End Function
Note that you also do not need to keep track of the placard number: you can add a newline to the end of the previous item on each pass after the first one.