Saving current document with password from macro

I looked for the “call macro via command line” myself in AP’s texts and didn’t find much more as already posted - and by that much less than I had expected.
May be kind of a rarely used track.
You surely already looked at soffice.exe -? ?
If you find a way to get the complete commandline from inside any instance created by the call of soffice.exe, please tell me.

So this is my script so far

sub save(inputFile as String, outputFile as String, password as String)
	
	dim doc as Object

	dim inputFileURL as string
	inputFileURL  = "file://" & inputFile
	
	dim outputFileURL as String
	outputFileURL  = "file://" & outputFile

	Dim saveEncryptedArgs(1) As New com.sun.star.beans.PropertyValue

	saveEncryptedArgs(0).Name  = "Password"
	saveEncryptedArgs(0).Value = password
	
	doc = stardesktop.LoadComponentFromURL(inputFileURL, "_blank", 0, Array())
	doc.storeAsURL(outputFileURL, saveEncryptedArgs)
	doc.close(True)

end sub

It mostly works, I can call it (from the terminal/bash) like so

soffice "macro:///Standard.Module1.save(\"[path to input document]\", \"[path to output document]\", \"[password]\")"
  1. Is there any way to call this macro using relative paths?
    instead of using the fully qualified path, do something like “./document.xlsx”?

  2. Is there a way to load a document from disk, without having to bring it up on the screen?
    When I call stardesktop.LoadComponentFromURL it opens the document in a new window, is there a way to load the document without opening it (visibly)?

You can use

	dim loadComponentProperties(0) As New com.sun.star.beans.PropertyValue

	PloadComponentPropertiesrops(0).Name= "Hidden"
	loadComponentProperties(0).Value= True

	doc = stardesktop.LoadComponentFromURL([path to input file], "_blank", 0, loadComponentProperties)

To “hide” the loaded document

I by no means have any idea what I’m really doing, I’ve only started using LibreOffice yesterday.

I don’t exactly understand what you mean by “complete commnadline”.

Seems there was a misunderstanding. Sorry.

I don’t know which article came first: this one, which is tagged 2019-10-24, or this November 15, 2021. But there is a link here and there to Pitonyak’s book - if you are just starting to teach LibreOffice to do useful things with macros, then I highly recommend downloading the book and having it handy. For example, Listing 5.111: Load hidden then setVisible answers your question “how to quietly open a document” - ah, I see, yuo already found this

If you want to do that with Ecel files, a license of MS Office should be affordable. Calc is an alternative to MS Excel but no replacement. This is not an alternative OOXML editor. As a matter of fact, OOXML has been introduced to fight Open Document Format (ODF).

The problem is, is that we have to use LibreOffice since were on Linux.
Using a VM is not an option so LibreOffice is out only option

Please never construct URLs like that, even on Linux. If you have a system path, use ConvertToURL.

Of course, your problem has nothing to do with the incorrect URL. The problem is that the script saves as ODF, regardless of the extension. You need to define the format in the args, as @Villeroy hinted.

    Dim saveEncryptedArgs(1) As New com.sun.star.beans.PropertyValue
    Dim EncryptionData(1) As New com.sun.star.beans.NamedValue

    EncryptionData(0).Name = "CryptoType"
    EncryptionData(0).Value = "Standard"
    EncryptionData(1).Name = "OOXPassword"
    EncryptionData(1).Value = password

    saveEncryptedArgs(0).Name = "FilterName"
    saveEncryptedArgs(0).Value = "Calc MS Excel 2007 XML"
    saveEncryptedArgs(1).Name = "EncryptionData"
    saveEncryptedArgs(1).Value = EncryptionData

Thanks for the reply, I’m off work now but I’ll try that tomorrow.
There’s a strange problem, whenever I tried specifying “Calc MS Excel 2007 XML” as the format, it always creates the document without encryption.
I’ll let you know soon

I’m sure you’ll be fine tomorrow.
I just created this file PleaseDontForgetPassword_NoWar.xlsx (8.5 KB)
using the command line

"C:\Program Files\LibreOffice\program\soffice.exe"  --headless --nologo "macro:///storeToXLSX.storeToXLSX.storeToXLSX(C:\TEMP\DemoPWD.ods,C:\Tests\PleaseDontForgetPassword_NoWar.xlsx,NoWar)

Yes, this is a command for Windows, but for your OS it will differ only in paths and file names.
By the way, how do you check that the resulting XLSX file will not open without a password? And then after all, most of us do not have Excel, Calc is enough for us.
By the way, why don’t you send ODS files to your clients with a recommendation to install LibreOffice?

2 Likes

If you try and open an encrypted document, LibreOffice/MS Word will give you a prompt to enter a password. Plus if you look at the contents of an encrypted documents it’s complete garbage until it’s decrypted.

For the same reason I can’t tell them to decrypt using GPG, it’s just not my call to make.

After all, it may happen that LibreOffice will require a password, and MS will simply open the file … Once upon a time, OpenOffice did this with MS files - it simply opened them, ignoring all protections. :slight_smile:

I liked the position that my house management took:
We work at the expense of residents’ payments, collect and store information about them in our computers. The person who paid us for this work has the right at any time to demand from us a summary - what kind of information we have collected about him (payment history, execution of his applications, etc.). We can give him such a certificate electronically. For example, in the form of several sheets in an Excel workbook. However, to see this information, a person will have to buy Excel. In other words, a person who has already paid money will be forced to pay more due to our data format. We push him to additional costs. On the other hand, if we give him data in the Open Data Format, he will be able to find out the contents of the given file almost for free (well, he will need a computer anyway).
Sorry for making you read so much text. But it seems to me that everyone should consider this position.

Our customers are mostly comprised of businesses/factories with laboratories, not individuals.
Almost all of them use Windows, and by extension MS-word. So me telling them to install another office program just to decrypt their data which we create, is not something I can do. I’m just a developer.

Don’t worry about it, I do appreciate the input

@JosefLintz You mentioned the MSWord a second time. It’s a typo? From the very beginning, it was about XLSX files, Excel workbooks. If the output file is needed in Word format, then the filter name must be different, “MS Word 2007 XML”

We are creating spreadsheets with the “.xlsx” file extension using C++, LibreOffice macro API is used to encrypt them (Unless something else is found).
When I say MS-word, I mean the LibreOffice equivalent for Microsoft/Windows. That’s the program our customers use to open the spreadsheet we send them.

Apologies if something’s unclear I’m fairly new to this whole spreadsheet thing

MS Word is an analog of LibreOffice Writer. For LibreOffice Calc, there is MS Excel. And the whole LibreOffice suite’s MS analog is called MS Office.

1 Like

Thank you so much, this worked perfectly. We’re even able to decrypt it from gmail.

For some reason every time I specified the “FilterName” as “Calc MS Excel 2007 XML” it didn’t encrypted the file.

This is the script right now

sub SaveWithPassword(inputFile as String, outputFile as String, password as String) as Integer
	
	' Convert file paths to a format LibreOffice can undersntad
	dim inputFileURL as string
	inputFileURL = ConvertToURL(inputFile)
	
	dim outputFileURL as String
	outputFileURL = ConvertToURL(outputFile)

	' Properties used to load the component
	dim loadComponentProperties(0) As New com.sun.star.beans.PropertyValue

	' Don't launch a new window when loading the document
	loadComponentProperties(0).Name = "Hidden"
	loadComponentProperties(0).Value = True


' If an error occured, jump to handleError label
on error goto handleError

	' Load the document
	dim doc as Object 
	doc = stardesktop.LoadComponentFromURL(inputFileURL, "_blank", 0, loadComponentProperties)

	
	' Output document encryption data
	Dim encryptionData(1) As New com.sun.star.beans.NamedValue

    encryptionData(0).Name = "CryptoType"
    encryptionData(0).Value = "Standard"
    encryptionData(1).Name = "OOXPassword"
    encryptionData(1).Value = password


	' Properties used when saving the document
	dim saveEncryptedArgs(1) As New com.sun.star.beans.PropertyValue


    saveEncryptedArgs(0).Name = "FilterName"
    saveEncryptedArgs(0).Value = "Calc MS Excel 2007 XML"
    
    saveEncryptedArgs(1).Name = "EncryptionData"
    saveEncryptedArgs(1).Value = encryptionData
	
	' Store this docuemnt with a password where specified.
	' Using storeAsURL might be preferred in our case, since we want to overwrite the documents
	' doc.storeToURL(outputFileURL, saveEncryptedArgs)
	doc.storeAsURL(outputFileURL, saveEncryptedArgs)
	
	' Close the document
	doc.close(True)
	
	' Return '1' (true) if succesfull
	 SaveWithPassword = 1
	
	exit sub
	
handleError:

	' Return '0' (false) if an error occured
 	SaveWithPasswor2 = 0

end sub

I may have just one last question. Is there a way to return a value from the script?
Because when I run the script from C++ it always returns 0 (I have other ways to verify that the script worked).

This clarifying question is not relevant to the original discussion

How do you call it?
Also, don’t forget about this syntax features:
image

Note the typo. There are possibly more - e.g., it’s unclear what “I have other ways to verify that the script worked” might mean, unless there’s a missing “no”, like “I have no other ways …” - or do you mean that you can workaround even if there’s no way to return a value?

A “script” term is used without clarification: does “script” mean the Basic sub (which, being sub, can’t return anything, as @JohnSUN mentioned)? Or is that a shell script - so you expect the soffice process to return an exit code? So that boils down to: do you use UNO API to control soffice from C++ (and so you are able to call e.g. XScript::invoke), or are you trying to use command line interface?

I have figured out a way to work around the limitation of the script returning only ‘0’ to verify that the script ran successfully. But, I’d prefer if I could actually return more specific results from the script itself.

When I say script, I mean a LibreOffice macro which can be run by a C++ program, atm I’m (very unfortunately) using system() to invoke the soffice. XScript::invoke seems very interesting, I’ll give it a try later