I have tried this, but get an error when saving the file:
X0 := ComObjCreate("Excel.Application") ;handle
X0.Visible := True ;by default excel sheets are invisible
X0.Workbooks.Add ;add a new workbook
X0.Range("A1").Value := "00123123" ;in Feld "A1" Text einfügen
Sleep 1000
test := "C:\test.xls"
X0.Excel.ActiveWorkbook.Save(test)
Can anybody tell me what I'm doing wrong?
oExcel := ComObjCreate("Excel.Application")
oExcel.Visible := True
oExcel.Workbooks.Add
oExcel.Range("A1").Value := "00123123
Sleep 1000
testpath := "C:\test.xls"
oExcel.ActiveWorkbook.SaveAs(testpath)
The SaveAs method is the thing you need http://msdn.microsoft.com/en-us/library/office/ff841185.aspx
Also this may help http://www.autohotkey.com/board/topic/56987-com-object-reference-autohotkey-l/page-10#entry418122
Related
I am trying to open an excel file from libreoffice calc's macro but I keep coming accross errors. This is my first time using libreoffice macro.
Here is my first attempt, was from a website where someone asked the same question so I tried there code: https://forum.openoffice.org/en/forum/viewtopic.php?f=5&t=17075
Target = "C:\Users\RKerrigan\Documents\Scripts\Mailerreportgenerator\Miller Radiology Mailers Template.xlsx"
TargetURL = convertToURL(Target)
Empty() = Array()
TestDoc = StarDesktop.loadComponentFromURL(TargetURL, "_blank", 0, Empty())
But the error I got was regarding line 6 (Empty() = Array()):
BASIC runtime error.
'382'
This property is read-only.
So then I searched around and found this link from stackoverflow: https://stackoverflow.com/a/65201568/16953756
Which brings you to this example:https://help.libreoffice.org/6.4/en-US/text/sbasic/shared/stardesktop.html
Dim docURL As String
Dim doc As Object, docProperties()
docURL = ConvertToURL("C:\\Users\\RKerrigan\\Documents\\Scripts\\Mailerreportgenerator\\Miller Radiology Mailers Template.xlsx")
Rem com.sun.star.frame.Desktop
doc = StarDesktop.LoadComponentFromURL(docURL, "_blank", 0, docProperties)
But I got another error saying:
BASIC runtime error.
'1'
Type: com.sun.star.lang.IllegalArgumentException
Message: Unsupported URL <file:///C://Users//RKerrigan//Documents//Scripts//Mailerreportgenerator//Miller%20Radiology%20Mailers%20Template.xlsx>: "type detection failed"
Can someone help me open this file in libreoffice macro? "C:\Users\RKerrigan\Documents\Scripts\Mailerreportgenerator\Miller Radiology Mailers Template.xlsx"
I thought it was something quotes so I tried double slashes and that didn't work either.
Please try
Sub OpenRadiologyMailers()
Dim sFilename As String
Dim oSourceSpreadsheet As Variant
sFilename = ConvertToURL("C:\Users\RKerrigan\Documents\Scripts\Mailerreportgenerator\Miller Radiology Mailers Template.xlsx")
If Not FileExists(sFilename) Then
MsgBox("File not found!")
Exit Sub
EndIf
GlobalScope.BasicLibraries.loadLibrary("Tools")
oSourceSpreadsheet = OpenDocument(sFilename, Array())
If IsEmpty(oSourceSpreadsheet) Then
MsgBox("The file may be open in another application",0,"Failed to load file")
Exit Sub
EndIf
' ... further actions with the document oSourceSpreadsheet
End Sub
In vb.net, I have my program run sqlite3.exe. Sqlite3 runs the following commands, which are stored in a text file:
.open prod.db
.mode csv
.output output.csv
SELECT STATEMENT
.output stdout
.exit
Once output.csv has been created, I then run a Streamreader to see what the results were and I get the following error:
The process cannot access the file 'output.csv' because it is being used by another process.
However, I know it is not locked up for long because I can go to the csv and open it manually after it is created.
I would write code to check to see when the process finishes, but I'm not sure what process is running to check this (I already check for SQLite3.exe to close). In other words, how do I know my csv is free for Streamreader to open?
Using droque's link"
VB.Net 3.5 Check if file is in use
I was able to combine this with some of my own code to fix the problem:
While FileInUse("output.csv") And j < 100
System.Threading.Thread.Sleep(100)
j += 1
End While
'Timeout after ~10 seconds
If j = 100 Then
MessageBox.Show("CSV timeout. Exiting now.")
Exit Sub
End If
where FileInUse is defined here:
Public Function FileInUse(ByVal sFile As String) As Boolean
Dim thisFileInUse As Boolean = False
If System.IO.File.Exists(sFile) Then
Try
Using f As New IO.FileStream(sFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
' thisFileInUse = False
End Using
Catch
thisFileInUse = True
End Try
End If
Return thisFileInUse
End Function
I have an autohotkey script which calls an Excel macro. Basically I have a universal shortcut to add a task to my custom GTD application in Excel
My AHK code is as follows:
RunMSExcelMacro(MacroName, args) { ; for AHK_L
oExcel := ComObjActive("Excel.Application")
; oExcel.Workbooks("gtd_active.xlsm").Run(MacroName,args)
oExcel.Run("'gtd_active.xlsm'!"+MacroName,args)
;oExcel.Run(MacroName,args)
}
#Space::
InputBox, newTask, Add New Task to GTD, What is the new task?, , 380, 130
if (newtask = "" or ErrorLevel){ ;if blank or "cancel" pressed (ErrorLevel = 1) don't do anything
return
}
else
{RunMSExcelMacro("addFromAHK", newTask)
}
return
The method in Excel is as follows:
'this script allows AutoHotKey to add items to the GTD list
'without having to even access Excel - wtf hax :-)
Sub addFromAHK(ByRef newTask As String)
Dim myCell As Range
'I don't like hardcoding this but I cant be bothered to
'make this reference the constant right now
Set myCell = MasterList.Range("C50000").End(xlUp)
'ugh such a hack. No easy way to get last cell without defiltering
Do Until IsEmpty(myCell) = True
Set myCell = myCell.Offset(1, 0)
Loop
'save the task
myCell.value = newTask
End Sub
Unfortunately, if I am currently editing a cell in Excel I cannot call a macro, so the global shortcut fails. Note this fails before I am able to call the Excel macro.
Is there an easy way to change the AHK code to basically "exit cell editing" if I'm doing that? I don't want to write a huge amount of code to do this but I'm really not sure the best approach here.
The first time I made use of AHK_L's try/catch (yay!). Check out this code example:
RunMyMacro() {
oExcel := ComObjActive("Excel.Application")
try {
oExcel.Run("'MyFile.xlsm'!TestSub")
} catch e {
ControlSend, , {Enter}, ahk_class XLMAIN
Sleep, 200
oExcel.Run("'MyFile.xlsm'!TestSub")
}
}
It's pretty basic, so you'll have to do the fine tuning yourself.
If there's an error calling the macro, we outright assume that that's because we are editing a cell. If you are rather meticulous, you could check the exception's message (e.Message) for an error code. On my machine the message was 0x80010001 Some German BlaBla.
To exit cell editing, we simply send Enter to the Excel Window. If there's multiple Excel Windows, you have to restrict the window title like MyFile.xlsm ahk_class XLMAIN.
After the Sleep (you may want to play around with the exact timeout), we call our macro again.
I have an application (for which I don't have control of the source), and it exposes a COM interface that works fine from VBA, for example:
Sub test()
Set myApp = CreateObject("MyApp.Application")
val1 = myApp.SubPart.Size
MsgBox CStr(val1)
myApp.SubPart.IncreaseSize
End Sub
This works perfectly. When I do the equivalent in AutoHotkey-L:
myApp := ComObjCreate("V6.Application")
val1 := myApp.SubPart.Size
MsgBox %val1%
myApp.SubPart.IncreaseSize
The message box fires, and gives me the correct value. The last line halts with an error:
0x80020003 - Member not found
Specifically: IncreaseSize
What can I do to get this to function the same in AHK?
For anyone else stuck with this, I solved it by first changing to use the 32-bit ANSI AutoHotkey executable. For me, this is at:
C:\Program Files\AutoHotkey\AutoHotkeyA32.exe
I then changed any COM method calls to be embedded into a ScriptControl call:
myApp := ComObjCreate("MyApp.Application")
val1 := myApp.SubPart.Size
MsgBox %val1%
SC := ComObjCreate("ScriptControl")
SC.Language := "VBScript"
SC.Timeout := -1
code =
(
Set MyApp = CreateObject("MyApp.Application")
MyApp.SubPart.IncreaseSize
)
sc.ExecuteStatement(code)
Of course, the Size read could be moved into the VB code block too.
I'm writing a macro which goes through a document and tries to parse it by Style. Right now, anything in the designated style is copied onto the immediate window. Is there a way to automate the macro further to move the text from the immediate window into a txt file? Otherwise, anyone using the macro would not be able to see the text unless they opened up VBA, correct?
Here's my suggestion: write to the immediate window AND to a file at the same time. Examples below.
Why make the information first transit in the immediate window, and only then write it to a file from there? That just sounds perversely and uselessly difficult!
Dim s As String
Dim n As Integer
n = FreeFile()
Open "C:\test.txt" For Output As #n
s = "Hello, world!"
Debug.Print s ' write to immediate
Print #n, s ' write to file
s = "Long time no see."
Debug.Print s
Write #n, s ' other way of writing to file
Close #n
Dim FSO As Scripting.FileSystemObject
Set FSO = New Scripting.FileSystemObject
Dim txs As Scripting.TextStream
Set txs = FSO.CreateTextFile("C:\test2.txt")
s = "I like chickpeas."
Debug.Print s ' still writing to immediate
txs.WriteLine s ' third way of writing to file
txs.Close
Set txs = Nothing
Set FSO = Nothing
Note that this last bit of code requires a reference to be set: Tools > References > checkmark at Microsoft Scripting Runtime.
Put this code to immediate window and hit enter to write the List to JSON text in C#.
System.IO.File.WriteAllText(#"C:\Users\m1028200\Desktop\Json2.txt",
JsonConvert.SerializeObject(resultsAll));
I would recommend to use some best-practices-based logging framework like VBA Logging, which supports file logging or console configurably in parallel etc.
example usage (e.g. in some Foo.bas module):
Sub MySub()
Logging.setModulName (Application.VBE.ActiveVBProject.Name)
Set log = Logging.getNewLogger(Application.VBE.ActiveVBProject.Name)
Call log.setLoggigParams(Logging.lgALL, True, True, True) ' log ALL to Console, Buffer, File
log.logINFO "This is my message ..", "MySub"
End Sub
resulting in something like (both in console and vba_logging.log file):
(16.12.2018 13:08:30)[XlsxMgr::MySub]-INFO: This is my message ..
where the log config file looks like this:
## vba_logging.properties
LOG_LEVEL = info
LOG_TO_CONSOLE = True
LOG_TO_BUFFER = True