access command line data in Excel VBA fails - excel

I need to access the command line parameters in an Excel VBA macro, and found many variations but only one that worked with Excel-2010, seems that the API has changed over time. I tried this code I found "out there":
Dim pCmdLine As Long ' Pointer to the Comand-line string
Dim strCmdLine As String ' Command line string
Dim CmdLine As String ' Command line string
' Get the pointer to the command line string
pCmdLine = GetCommandLineA
' Fill the string with zeros
' (300 characters for command line seems to be enough)
strCmdLine = String$(300, vbNullChar)
' Copy from the pointer to VBA-style string
lstrcpynA strCmdLine, pCmdLine, Len(strCmdLine)
' At this point we got the string,
' now skip the rest of it filled with 0 characters.
CmdLine = Left(strCmdLine, InStr(1, strCmdLine, vbNullChar) - 1)
MsgBox "Length of the command line = " & Len(CmdLine) '' Debug
MsgBox "Command Line:: " & CmdLine '' Debug
Which I put into the Auto_open macro of a spreadsheet. If I try this call:
start excel TestMacro.xlsm /e/abcd/xyz
It seems to generally work and the macro reports:
Command line = " C:/.../excel.exe TestMacro.xlsm"
So I get the invocation part, but the parameters are lost.
Partial Solution:
I find that if I change the invocation to:
start excel /e/abcd/xyz TestMacro.xlsm
It works, except the parsing code has to be changed to ignore the file name which is not at the end, and also this form doesn't seem to allow any blanks in any parameter, even if quoted. The system seems to interpret them as file names for a target excel file and give an error. For example:
start excel /e/abc/"my sheet"/ TestMacro.xlsm
gives the error:
file 'sheet"/.xlsx' not found
Although after the spurious startup error, the intended sheet does open and get teh entire line to work with.

Related

How to avoid carriage return when using #print with excel vba [duplicate]

With Visual Basic, I'm confused with that the behavior of Print statement in that sometimes the following statement: would cause additional carriage return "^M" at the end of a line, but sometimes, it doesn't. I wondering why?
filePath = "d:\tmp\FAE-IMM-Report-2012-Week.org"
If Dir(filePath) <> "" Then
Kill filePath
End If
outFile = FreeFile()
Open filePath For Output As outFile
Print #outFile, "#+TITLE: Weekly Report"
would produce
#+TITLE: Weekly Report^M
while I wish without ^M:
#+TITLE: Weekly Report
In one test program, almost the same code would produce no "^M".
Please help! Thanks a lot.
Upon further experiment, I found that the following suggestion using vbNewline and ";" at the end of print content, still does not solve my problem.
After careful isolation, I found the cause of the problem is an character that seems like a space, not exactly space, followed by newline and carriage return. Before printing the text containing the offending string, there was no carriage return, but once the offending line is printed, then every line including the previous line printed would have carriage return.
I'm not sure what the exact the offending string is as my skill of VBA is not yet too well.
Here is a copy of the offending text from a spreadsheet cell:
"There is something invisible after this visible text
After the invisible text, then there might be a carriage return $Chr(13) and/or newline"
I'm not sure if the paste to web browser would preserve the content, though. By pasting to emacs, I did not see carriage return, while emacs should display it, if there is one. So I guess that there is no carriage return in the offending string.
Below is the program demonstrate the problem:
Sub DemoCarriageReturnWillAppear()
Dim filePath As String
Dim outFile
Dim offendingText
filePath = "d:\tmp\demoCarriageReturn.org"
If Dir(filePath) <> "" Then
Kill filePath
End If
outFile = FreeFile()
Open filePath For Output As outFile
Print #outFile, "#+AUTHOR: Yu Shen" & vbNewLine;
Close #outFile 'At this moment, there is no carriage return
Open filePath For Append As outFile
offendingText = ThisWorkbook.Worksheets("Sheet1").Range("A1")
Print #outFile, offendingText & vbNewLine;
Close #outFile 'Now, every line end has carriage return.
'It must be caused by something offending at the above print out content.
End Sub
Here is the final result of the above procedure:
#+AUTHOR: Yu Shen^M
There is something invisible after this visible text
After the invisible text, then there might be a carriage return $Chr(13) or newline^M
Note the above "^M" is added by me, as carriage return would not be visible in browser.
If you're interested, I can send you the excel file with the offending content.
I need your help on how to avoid those offending string, or the carriage returns.
(I even try to do string Replace of the carriage return or new line, as I found that once I manually deleted whatever caused change to another line, the problem would be gone. But calling Replace to replace vbNewline, Chr$(13), or vbCrLf did not make any difference.
Thanks for your further help!
Yu
Use a trailing semicolon to surpress the new line:
Print #outFile, "#+TITLE: Weekly Report";
^
^
The VB Editor will often add a semicolon if you make a mistake in the statement which could explain why the new line is sometimes output and sometimes not.
New diagnostic routine
We need to know the character within cell A1 that is causing the problem.
Place the following subroutine within one of your modules.
Public Sub DsplInHex(Stg As String)
Dim Pos As Long
For Pos = 1 To Len(Stg)
Debug.Print Hex(AscW(Mid(Stg, Pos, 1))) & " ";
Next
Debug.Print
End Sub
Go to VB Editor's Immediate window and type in the following text following by Return:
DsplInHex(Sheets("Sheet1").range("A1"))
Underneath this line, you should see something like 54 65 73 74 31. This is a list of the code value of each character in the cell. I expect we will see A, the code for line feed, or D, the code for carriage return, at the end of the list.
Position the cursor in cell A1. Click F2 to select edit then Backspace to delete the invisible trailing character then Return to end the edit. Go back to the Immediate Window, position the cursor to the end of DsplInHex(Sheets("Sheet1").range("A1")) and click Return. The trailing character should have gone.
Try that and report back. Good luck.
To help the other people in the future, here is an summary of my problem and the solution. The extra carriage return on each line even with semi-colon at the print statement end was actually caused by a string of space followed by newline (Chr$(A)) in one of the print statement, once such string is printed, then all previous and subsequent printed content would have an extra carriage return!
It seems a bug on VBA 6 (with Excel 2007), a nasty one!
My work-around was to replace the newline by a space.
Thanks for Tony's repeated help enabling me finally nailed down the cause.
Here is the code to demonstrate the problem:
Sub DemoCarriageReturnWillAppearOnAllLines()
Dim filePath As String
Dim outFile
Dim offendingText
filePath = "d:\tmp\demoCarriageReturn.org"
If Dir(filePath) <> "" Then
Kill filePath
End If
outFile = FreeFile()
Open filePath For Output As outFile
Print #outFile, "#+AUTHOR: Yu Shen" & vbNewLine;
Close #outFile 'At this moment, there is no carriage return
Open filePath For Append As outFile
offendingText = " " & Chr$(10)
Print #outFile, offendingText & vbNewLine;
Close #outFile 'Now, every line end has carriage return.
'It must be caused by the offending at the above print out content.
End Sub
After the first "Close #outFile", here is the content of the file demoCarriageReturn.org:
#+AUTHOR: Yu Shen
Note: with editor capable showing carriage return as visible ^M, there is no carriage return present.
However, after the second "Close #outFile", here is the content of the same file with additional content:
#+AUTHOR: Yu Shen^M
^M
Note: there are two carriage returns appear. They are not intended. Especially, to the first line, the print statement has been executed, and at the previous close statement, it was found without carriage return. (To illustrate carriage return, I have to typing ^M in web page here. But it's in the file of the print out.)
This is why I think that it's a bug, as the carriage returns are not intended. It's undesirable surprise.
The following code shows that if I filter out the linefeed character the problem would be gone.
Sub DemoCarriageReturnWillNotAppearAtAll()
Dim filePath As String
Dim outFile
Dim offendingText
filePath = "d:\tmp\demoCarriageReturn.org"
If Dir(filePath) <> "" Then
Kill filePath
End If
outFile = FreeFile()
Open filePath For Output As outFile
Print #outFile, "#+AUTHOR: Yu Shen" & vbNewLine;
Close #outFile 'At this moment, there is no carriage return
Open filePath For Append As outFile
offendingText = " " & Chr$(10)
Print #outFile, Replace(offendingText, Chr$(10), "") & vbNewLine;
Close #outFile 'Now, no more carriage return.
'The only change is removing the linefeed character in the second print statement
End Sub
After full execution of the above program, there is indeed no carriage return!
#+AUTHOR: Yu Shen
This shows that string combination of space followed by linefeed caused the bug, and removing linefeed can avoid the bug.
The following code further demonstrate that if there is no offending string, even without newline and semi-colon at the end of print statement, there would not be undesired carriage return!
Sub DemoCarriageReturnWillNotAppearAtAllEvenWithoutNewLineFollowedBySemiColon()
Dim filePath As String
Dim outFile
Dim offendingText
filePath = "d:\tmp\demoCarriageReturn.org"
If Dir(filePath) <> "" Then
Kill filePath
End If
outFile = FreeFile()
Open filePath For Output As outFile
Print #outFile, "#+AUTHOR: Yu Shen"
Close #outFile 'At this moment, there is no carriage return
Open filePath For Append As outFile
offendingText = " " & Chr$(10)
Print #outFile, Replace(offendingText, Chr$(10), "")
Close #outFile 'Now, no more carriage return.
'The real change is removing the linefeed character in the second print statement
End Sub
Also in the output result:
#+AUTHOR: Yu Shen
Still no the annoying carriage return!
This shows that using newline followed by semi-colon at the end of print statement is not the solution to the problem of carriage return at every line! The real solution is to avoid any string of space followed by linefeed in the print out content.
Yu

Search txt and csv files for string using Excel VBA without opening files

I have a text file that is automatically generated from a machine. The machine writes the txt file in "chunks" (sorry I don't know the exact terminology). I need to pull data from this txt file, but I need the txt file to be finished before pulling data from it. I found a solution to verify that the machine has finished writing to the file... It is not as elegant as i had hoped, but seems to do the trick. Excel VBA opens a command prompt, the command prompt uses a Find command to find the string "End of Report"... This is basically one of the last lines of the txt file and pretty safe to assume the txt file is finished after this is found. This code runs in a loop 1000 times, every 10 seconds, until it finds this string or reaches 1000 tries...
The issue is that "result" returns some other characters besides just "End of Report" this is further complicated by the fact that I am attempting to run this on some csv files too... and "result" returns some additional characters also, but different from the ones returned from the txt files. For example, if I check the length of "result"... The length comes back as 43 on one file and 48 on another file... I think it is counting the file path + "End of Report" + a few more characters?
Anyways, I don't really need the "result"... I really only need a "true" / "false" if "Find" found "End of Report" or not... How can I accomplish this? Is there a different better way to do this? I am not familiar with command prompt programming.
Note: It is important that I search these files without opening them.
Sub test()
Dim SearchStr As String
Dim cmdLine As Object
Dim result As String
Dim FilePath As String
FilePath = "D:\test2.txt"
SearchStr = """End of Report"""
Set cmdLine = CreateObject("WScript.Shell")
result = cmdLine.Exec("%comspec% /C Find " & SearchStr & " " & Chr(34) & FilePath & Chr(34)).STDOut.ReadAll
Debug.Print (result)
End Sub
I am not really an expert in command line, but what I would do is export the result of the FIND command to a file, like here
Then I would check in your VBA code how many rows are in the file (either clean the file before, or check the number of rows before the export is done).
If the number of rows meets the criteria (probably 2 or more rows instead of 1), then you can set the flag to True.

VBScript - Output command to file

I am using secureCRT to connect to a Linux server. SecureCRT reads VBScript, and I am new to this language so my problem might sound easy for you.
When I connect to the server from secureCRT, I a script containing a command let's say "date" ,the output of the command must come out on a text file on my local host ( windows ) and not on the server.
This is the script that I am using:
# $language = "VBScript"
# $interface = "1.0"
' This script demonstrates how to capture line by line output
' from a command sent to a server. It then saves each line of output
' to a file. This script shows how the 'WaitForStrings' command can be
' used to wait for multiple possible outputs.
' Constants used by OpenTextFile()
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Sub Main
crt.Screen.Synchronous = True
' Create an instance of the scripting filesystem runtime so we can
' manipulate files.
'
Dim fso, file
Set fso = CreateObject("Scripting.FileSystemObject")
' Open a file for writing. The last True parameter causes the file
' to be created if it doesn't exist.
'
Set file = fso.OpenTextFile("C:\Users\elieme\Desktop\TTX1.txt", ForWriting, True)
' Send the initial command then throw out the first linefeed that we
' see by waiting for it.
'
crt.Screen.Send "gsh list_imsins" & Chr(10)
crt.Screen.WaitForString Chr(10)
' Create an array of strings to wait for.
'
Dim waitStrs
waitStrs = Array( Chr(10), "linux$" )
Dim row, screenrow, readline, items
row = 1
Do
While True
' Wait for the linefeed at the end of each line, or the shell prompt
' that indicates we're done.
'
result = crt.Screen.WaitForStrings( waitStrs )
' If we saw the prompt, we're done.
If result = 2 Then
Exit Do
End If
' The result was 1 (we got a linefeed, indicating that we received
' another line of of output). Fetch current row number of the
' cursor and read the first 20 characters from the screen on that row.
'
' This shows how the 'Get' function can be used to read line-oriented
' output from a command, Subtract 1 from the currentRow to since the
' linefeed moved currentRow down by one.
'
screenrow = crt.screen.CurrentRow - 1
readline = crt.Screen.Get(screenrow, 1, screenrow, 45 )
' NOTE: We read 20 characters from the screen 'readline' may contain
' trailing whitespace if the data was less than 20 characters wide.
' Write the line out with an appended '\r\n'
file.Write readline & vbCrLf
Wend
Loop
crt.screen.synchronous = false
End Sub
I read the script several time to understand it, and tried to manipulate it for hours, and asking for help was my last resort.
In the script I have crt.Screen.Send "date" & Chr(10) which will send my command and execute it. Then when I go in the loop, I don't understand what does this mean.
'If we saw the prompt, we're done.
If result = 2 Then
Exit Do
End If
What do they mean by if we saw the prompt? Is it something that i have to input for it to exit ? Because i tried several keys and I'm always stuck in this while loop.
I tried to manipulate the script but every time I was either getting an empty file as output, or wrong data in the file.
Is there anyway to make this script execute only the command that I sent ("date"), and output what this command will do on the text file ?
If not, is there any shortcut to stop the script without having to go in the menu and selecting cancel script?
Thank you
EDIT:
I fixed it guys, very easy.
The rt.Screen.WaitForStrings takes as a second parameter a timeout number, so that fixed everything.
Thanks
Fixed
The rt.Screen.WaitForStrings takes as a second parameter a timeout number, so that fixed everything.

VB: Highlight Excel cell in worksheet

I was wondering if it was possible to create a vbs file to highlight a cell in an excel workbook.
I have an excel worksheet with multiple computer host-names, I also run a script in batch that pings each host-name in a text document. I want to call the vbs file to highlight the cell in excel if the ping result was successful. Is this possible?
Thanks!
Dimitri
There are plenty of ways to do this, but I must ask why you're using a batch script and a text file to ping the hostnames when you can do that right in Excel?
There are two ways to do this... one is a bit more complex and correct and the other is quick and dirty. Frankly, I recommend the quick and dirty.
Correct Way:
Declare the ReadConsole & WriteConsole methods from your Windows kernel32.dll and utilize them to get the results of your ping. It's described well here:
http://visualbasic.about.com/od/learnvb6/l/bldykvb6dosa.htm
Q&D Way:
Use the built-in Shell() function in VBA and pipe the output of the ping to a text file. Parse said text file and delete it when you're done.
e.g.
for each currCell in hostnameRange
' Ping each hostname and pipe the results to a file
shell "ping " + currCell.value + " >> ping_result.txt"
next currCell
inFile = FreeFile()
Open "ping_result.txt" for Input as #inFile
fileBuffer = Input$(LOF(inFile ), inFile) ' Open and read the file to a buffer
for each currCell in hostnameRange
' Search for ping failures in the buffer
if instr(1, fileBuffer, "could not find host " + currCell.value) = 0 then
debug.print "Ping successful."
end if
next currCell

Excel VbScript Quotes issue

I am using Vbscript to write some data into excel then i am saving this excel object as txt file. My problem here is after saving as text file some rows contains quotes ". Below is my code can some body help me recording this.
My Output text file is:
"Rules*V*ZBEA*892**0010*10*IBM-01**"
30,000.00*01/08/2012*21/08/2012****0000013556*01***2600
"Scale value* *********"
problem here is 1st and 3rd row starts and ends with quotes (" ").
code is
Dim objXL1,name
Set objXL1 = CreateObject("Excel.Application")
objXL1.Workbooks.Add
objXL1.Cells(1 ,1) = "Rules*V*ZBEA*892**0010*10*IBM-01** "
objXL1.Cells(2,1) = "30,000.00*01/08/2012*21/08/2012****0000013556*01***2600"
objXL1.Cells(3 ,1) = "Scale value* *********"
name = objXL1.GetSaveAsFilename(,"Text(MS-DOS)(*.txt),*.txt")
objXL1.ActiveWorkbook.SaveAs name ,21 ,,21
objXL1.ActiveWorkbook.Close 0
objXL1.quit
And here once more issue is I am using SaveAs method for getting file name. When execution comes to this line the file save dialog box hiding behind the main IE window is there any way to get this save dialog box in focus?
I assume this is because of the whitespace. In your code there is a trailing whitespace in the frist line.
"Rules*V*ZBEA*892**0010*10*IBM-01** "
-----------------------------------^-
If you would export multiple cells you would need to encapsualte those cells to recognize where a cell value begins and ends.

Resources