I am calling one .NET app from another using Process.Start and passing in a bunch of strings as command line arguments:
startInfo.Arguments = String.Join(""" """, MyArray)
Dim p As Process = Process.Start(startInfo)
My intent is to pass in something like:
"first value" "second value" "third value"
and retrieve from within the second app:
Sub Main(ByVal args() as String)
If args.Length > 0 Then
End If
...
End Sub
Unfortunately args.Length only returns 1 - all the values I pass get passed on as a single value: "first value second value third value"
I tried wrapping each in double quotes in the first app but does not seem to help. I know I can just retrieve args(0) and then split it into an array of values but I do not want to do that. Also somehow it worked for me before, even without double quotes. So I am trying to figure out what happened and how can I make it pass my strings as multiple values instead of 1.
Your String.Join is not going to give you what you want. It will not put the double quote at the start and end of the string.
startInfo.Arguments = """" + String.Join(""" """, MyArray) + """"
Related
Ok,
To all those who may come across this question, this is a problem I have been banging my head against for the past two weeks and have made little or no progress, so any help would be extremely welcome.
Here's the set up; then I will follow with an excerpt of the code I have written:
I am writing a function to get a very specific formula for each file name in a given folder. This naturally requires me to write a program which can take string arguments (in this case, excel file names) from a very broad domain of possibilities and yield a very specific output based on some key -and highly unique- parameters. Hence, my function is bijective and the set of arguments and set of products are massive; therefore, I am in the process of writing a sub-process for this function which partitions the string argument, by character, into a corresponding array, remove all the unnecessary characters, concatenate the remaining characters into the output string, and then go through a series of checks to enforce whatever name-formula the file requires. For now, I am just focused on splitting the string into an array, removing all non-numeric characters and combining the remaining characters back into a single string.
Naturally, I have tried the split function, but to my knowledge VBA doesn't support the splitting of a string into single characters. So I have written the following code, which, admittedly, is a bit inelegant, but I think in principle must work. -It does not. Would someone kindly tell me why it doesn't, and make a recommendation for altering it.
Dim arr() As Variant
For i = Len(strArg) To i = 1
If IsNumeric(Mid$(strArg, i, 1)) = True Then
arr(i - 1) = Mid$(strArg, i, 1)
Else: arr(i - 1) = ""
End If
Next
newStr = Join(arr())
arr() always returns empty, so newStr is always "". Yet there are always numeric values in each string argument. -I can't imagine why I am getting this result. If I use ReDim arr(Len(strArg)), I get Len(strArg) number of " " back....
Thanks in advance to whomever may provide help.
Not sure why you need to split it into an array for this. Your description says you only want to have numeric characters returned in a new string variable. A function like this should work for you:
Function GetNumbers(ByVal arg_sText As String) As String
Dim i As Long
Dim sChar As String
Dim sNumbers As String
For i = 1 To Len(arg_sText)
sChar = Mid(arg_sText, i, 1)
If IsNumeric(sChar) Then sNumbers = sNumbers & sChar
Next i
GetNumbers = sNumbers
End Function
Then just call it in your code like this:
newStr = GetNumbers(strArg) 'Example: "ab1c2d" = "12"
Alternatively use a Regular Expression
Function NumOnly(s As String) As String
With CreateObject("VBScript.RegExp")
.Global = True
.MultiLine = False
.IgnoreCase = True
.Pattern = "[^0-9]+"
NumOnly = .Replace(s, "")
End With
End Function
As a further approach to the existing solutions, I'd like to demonstrate how to use the ►FilterXML() function and to check valid results.
The proposed function NumsOnly() consists only of three steps:
a) execute an XPath search upon xml content which has been created by getXML()
b) check valid results via procedure check
c) return the function result as new formed string
Coming close to the requirements in OP this includes also a way to
convert a string to a single character array (c.f. #JNevill 's comment to OP) and
to build a well-formed xml string as base for Filter.XML (see function getXML()) .
Main function NumsOnly()
Function NumsOnly(ByVal s As String) As String
'Purp: recognizes only numeric values in comparisons
'Note: no findings and single digit results are handled by proc check
Const xpath As String = "//*[.>0]" ' get only digits out of atomized characters
'a) execute XPath search upon xml content
Dim x: x = Application.FilterXML(getXML(s), xpath)
'b) check valid results
check x
'c) return only-nums string as function result
NumsOnly = x
End Function
Helper function getXML()
Extended udf based on Split string into array of characters?
Function getXML(ByVal s As String)
'Purp: return well-formed xml content string as base for FilterXML function
'1) atomize string elements into array
Dim buff() As String: buff = Split(StrConv(s, vbUnicode), Chr$(0))
ReDim Preserve buff(UBound(buff) - 1)
'2) return valid xml content string
getXML = "<ch><c>" & Join(buff, "</c><c>") & "</c></ch>"
End Function
Procedure check
As FilterXML returns findings of more than one element as a 2-dim array,
non-findings as Error 2015 and a single element as stand-alone value, it is necessary to distinguish between the returned var types:
Sub check(ByRef x, Optional ErrorResult As String = "")
'Purp: provide for correct xml result by checking var types
Select Case VarType(x)
Case vbError ' non-findings (Error 2015)
x = ErrorResult
Case Is >= vbArray ' 2-dim results (if more than 1 element)
x = Join(Application.Transpose(x), vbNullString)
'Case Else ' single element (here: digit, i.e. Double)
End Select
End Sub
Overview
I am trying to create a User Defined Function where I want to pass three strings (cell values) — Value1, Value2 and Value3, pass them to an array and then use the Join Function to concatenate them using a New-Line character and adding a custom text as prefix before each string.
Target
But before I join them, I want to ensure none of the parameters passed are empty strings. I am trying to use VBA Filter function to detect non-empty strings passed in the array and then join them.
Where am I getting stuck
However, if I pass "" or vbNullString as Match parameter and set the Include parameter to 'False', the VBA Filter function is not able to detect non-empty strings. I have also used the Trim function to ensure that none of the strings passed in the array contain whitespaces.
Can I use some wildcard characters to ensure that the strings contain at least one or more characters? I have tried passing "*?" characters in the Match argument and set Include parameter to 'True' but it does not work.
Question
Is there a possible way to use VBA Filter Function, possibly with wildcard characters?
Via function GetInfotext() I demonstrate how to
use a ParamArray argument,
filter out empty strings by help procedure RemoveEmpty (see a),
concatenate custom prefixes with the found non-empty strings (see b).
Example call
Sub ExampleCall()
Debug.Print GetInfotext("Intro", "", "bla bla")
End Sub
Function GetInfotext(ParamArray s()) As String
Dim tmp: tmp = s
'a) get non-empty elements
RemoveEmpty tmp
'b) add custion prefixes
AddPrefixes tmp, s
'c) return entire text
GetInfotext = Join(tmp, vbNewLine)
End Function
Result in VB Editor's immediate window:
X: Intro
Z: bla bla
Help procedures to GetInfoText
The main requirement in OP is to filter out empty string elements; as blanks would be found in any element and there are no special wild cards for them, it's necessary to identify empty elements by an
unused unique character, e.g. $, so eventual negative filtering allows to remove these marked elements.
Note that the double replacement is necessary to allow to mark consecutive empty elements by the $ mark, as VBA would skip several replacing characters here.
Sub RemoveEmpty(arr)
Dim tmp
tmp = Replace(Replace(Join(arr, "|"), "||", "|$|"), "||", "|$|")
arr = Filter(Split(tmp, "|"), "$", False)
End Sub
In order to check how to add the found elements to your custom prefixes, you might use the following help procedure:
Sub AddPrefixes(tmp, ParamArray s())
'define custom prefixes -- change to your needs
Dim prfx() As Variant
prfx = Array("X: ", "Y: ", "Z: ")
'concatenate them with passed non-empty elements
Dim i As Long, ii As Long
For i = LBound(prfx) To UBound(prfx)
If Len(s(0)(i)) Then tmp(ii) = prfx(i) & tmp(ii): ii = ii + 1
Next
End Sub
I'm trying to display this separated string in one message box rather than them all popping up separately one after another. Any help would be greatly appreciated!
Dim variables As String
Dim count As Integer
Dim arrResult() As String
variables = "3.09, 1.26, 3.4, 2.098"
arrResult = variables.Split(",")
For count = 0 To arrResult.Length - 1
MsgBox(arrResult(count))
Next
There's two way you could go about it.
FIRST
Before your loop, you could declare a variable say Dim allElements As String = "" then
replace your MsgBox(arrResult(count)) inside your loop to allElements &= arrResult(count) & vbNewLine, finally after your loop MsgBox(allElements)
SECOND
Just remove your loop, then use MsgBox(variables)
I am doing a loop for each string in an array such that
filename = Array(file1,file2.....file600)
However VBA gets a compile error that is due to the array taking up 8 lines. As far as I am aware it only allows 1 line
(error says expected list or separator)
I am new to VBA sorry
You can escape new lines in VBA with _.
so your solution might look like
filename = Array("file1", _
"file2", _
"file3")
See How to break long string to multiple lines and If Statement With Multiple Lines
If you have 100's of names, however, you might be better off storing them in a worksheet and reading them in, rather than hard-coding them.
Should you strings in the array be actually "buildable" following a pattern (like per your examples: "file1", "file2", ...,"file600") then you could have a Function define them for you, like follows:
Function GetFileNames(nFiles As Long) As String()
Dim iFile As Long
ReDim filenames(1 To nFiles) As String
For iFile = 1 To nFiles
filenames(iFile) = "file" & iFile
Next
GetFileNames = filenames
End Function
which you'd call in your "main" code as follows
Sub main()
Dim filenames() As String
filenames = GetFileNames(600) '<--| this way'filenames' array gets filled with 600 hundred values like "file1", "file2" and so on
End Sub
The amount of code that can be loaded into a form, class, or standard module is limited to 65,534 lines. A single line of code can consist of up to 1023 bytes. Up to 256 blank spaces can precede the actual text on a single line, and no more than twenty-four line-continuation characters ( _) can be included in a single logical line.
From VB6's Help.
when programming, you don't build an array this big mannually, never.
either you store each multiline-string inside a Cell, and at the end you buid the array like this :
option Explicit
Sub ArrayBuild ()
Dim Filenames() 'as variant , and yes i presume when using multi files, the variable name should have an "s"
With Thisworkbook.sheets("temp") 'or other name of sheet
Max = .cells(.rows.count,1).end(xlup).row '=max number of rows in column 1
Filenames = .range( .cells(1,1) , .cells(Max,1)).value2 ' this example uses a one column range from a1 to a[max] , but you could also use a multi column by changing the second .cells to `.cells(Max, ColMax)`
end with
'do stuff
erase Filenames 'free memory
End Sub
An other way is to build an array like you build a house by adding one brick at a time, like this :
Dim Filenames() as string 'this time you can declare as string, but not in the previous example
Dim i& 'counter
For i=1 to Max 'same max as in previous example, adapt code plz...
redim Preserve Filenames (1 to ubound(filenames)+1) 'this is an example for unknown size array wich grows, but in your case you know the size (here Max, so you could declare it `Dim Filenames (1 to Max)` from the start, just wanted to show every option here.
Filenames(i) = Cells (i,1).value2 'for example, but can be anything else. Also i'm beeing lazy and did not reference the cell to its sheet, wich i'd never do in actual coding...
next i
EDIT i did re-read your Question, and it is even easier (basically because you ommited the bracets in your post and corrected it as comment...), use
user3598756 's code plz. I thought File1 is a variable, when it should be written as "File1" .
EDIT 2 why bother build and array where Filename(x)="Filex" anyway? you know the result beforehand
I'm totally stumped on why this isn't returning a value. This set of functions is supposed to return the SUM of all the ASCII values in a String. The String and Number arrays build properly and the SUM function works on the Array, however when it tries to assign that summed value to the return variable, it fails.
By "it fails" I mean that the code does not step to the sum line and the function returns #VALUE! to the worksheet. Everything else checks out in the immediate window and steps through properly until the last line. Any suggestions are appreciated.
Private Function StringToCharArray(ByRef sIn As String) As String()
StringToCharArray = Split(StrConv(sIn, vbUnicode), Chr(0))
'provided by Fencliff at http://www.mrexcel.com/forum/excel-questions/342725-split-string-into-array.html
End Function
Function StringToNumber(MyString As String) As Integer
Dim StringArray() As String
Dim NumberArray() As Long
StringArray() = StringToCharArray(MyString)
ReDim NumberArray(UBound(StringArray))
For i = LBound(StringArray) To UBound(StringArray)
NumberArray(i) = Asc(StringArray(i))
Next i
StringToNumber = Application.WorksheetFunction.Sum(NumberArray)
End Function
Using an example of "abc" the Split obtains an array "a", "b", "c", "". That is, with an empty string element at the end. This cannot be converted to an ascii number so causes the error.
A simplistic solution is to skip this last element:
For i = LBound(StringArray) To UBound(StringArray) - 1
I suspect the problem (the extra element) is related to the use of Unicode but I haven't investigated this.