Hello @LadyFitzgerald,
My apologies for the longer delay, i hope this matter is still of interest to you…
Here goes:
The method Writer_Save_New()
is the one to be connected to a Keyboard Shortcut, a Button Command, and/or a Menu item Command, so that it can be invoked whenever you want to save a new Writer document.
If it is a New document, then the above procedure is performed; if it is not a New document, then the normal save procedure is performed.
A note about the dialog:
The “Save Dialog” implementation presented below in the function FileSaveDialog_Simple()
has fewer features than the dialog that pops up when you choose “Save As…” in LibreOffice. For example it lacks the features of setting a Password, saving the current Selection Only, Editing Filter Options, etc.
However for the purpose of this question, it will suffice.
Steps to perform:
EDIT 1 ( 2018-01-25 )
A) How to Copy-paste a Basic macro into your [My Macros & Dialogs].Standard Basic Library:
- Select all text in the code section below, and copy it to the Clipboard by pressing
CTRL+C
;
- In Writer, select the menu
Tools : Macros : Edit Macros
;
- In the Macro IDE Window that appears, in the “Object Catalog” on the left, doubleclick on the item called
My Macros & Dialogs
so that it expands;
- In the expanded section under “My Macros & Dialogs”, doubleclick on the item called
Standard
so that it expands;
- In the expanded section under “Standard”, doubleclick on any item so that it expands ( for example on the item called
Module1
); At the right side of the Macro IDE Window there should now appear all the text contents of the selected Module;
- Scroll down to the end of the Module, insert a few empty lines at the end by pressing the ENTER key, then paste all the copied text from the Clipboard by pressing
CTRL+V
.
- Save the Module by pressing
CTRL+S
.
B) How to Connect a macro to a Keyboard Shortcut:
- In Writer, select the menu
Tools : Customize...
;
- In the dialog that appears, select the tab
Keyboard
;
- In the “Shortcut Keys” listbox, scroll down to the Shortcut Key that you would like to use ( in this case i would recommend
Shift+Ctrl+Alt+S
), and select it;
- In the “Category” listbox, scroll down to the item called
LibreOffice Macros
, and doubleclick on it so that it expands;
- In the expanded section under “LibreOffice Macros”, doubleclick on the item called
My Macros
so that it expands;
- In the expanded section under “My Macros”, doubleclick on the item called
Standard
so that it expands;
- In the expanded section under “Standard”, doubleclick on the Module that contains the methods added in step A), e.g.
Module1
;
- In the “Function” listbox, scroll down to the item called
Writer_SaveNew()
, and select it;
- Click the
Modify
button;
- Click the
OK
button.
Code:
Sub Writer_SaveNew()
REM See: https://ask.libreoffice.org/t/capturing-title-in-writer-document-saved-filename/27519
REM If the current Writer document is new, then this method will invoke the File Save dialog with the first
REM sentence from the current Writer Document as the suggested file name.
REM If this method is called when the current Writer document is not new, it will just save it without any dialog.
REM Requires additional methods:
REM Writer_getSentence()
REM cutStringAtMarks()
REM FileSaveDialog_Simple()
Dim oDoc As Object : oDoc = ThisComponent
If Not oDoc.SupportsService( "com.sun.star.text.TextDocument" ) Then Exit Sub
If oDoc.hasLocation() Then REM the current document is not New:
oDoc.store() REM just save it immediately.
Else REM The current document is New:
REM open the Save File dialog with a custom file name.
REM **** Set here the maximum length for the filename ( excluding the file extension ):
Const iMaxLength As Integer = 60 REM Set to 0 for No Maximum.
REM **** Add here your desired punctuation marks to cut the filename at:
Dim aPunctuation() : aPunctuation = Array( ":", ";", "," )
REM **** Add here your characters to be removed from the filename:
Dim aForbiddenChars() : aForbiddenChars = Array( "/", "\", "|", ":", """", "?", "*", "<", ">" )
REM Get the 1st non-empty sentence...
Dim strDefaultName As String
strDefaultName = Writer_getSentence( 1, oDoc )
REM Cut the sentence at punctuation marks...
strDefaultName = cutStringAtMarks( strDefaultName, aPunctuation )
REM Remove illegal characters...
Dim i As Integer
For i = 0 To 31 REM Remove all ASCII characters < 31...
If Instr( strDefaultName, chr(i) ) > 0 Then strDefaultName = Join( Split( strDefaultName, chr(i) ), "" )
Next i
For i = 0 To uBound( aForbiddenChars ) REM Remove forbidden characters...
If Instr( strDefaultName, aForbiddenChars(i) ) > 0 Then strDefaultName = Join( Split( strDefaultName, aForbiddenChars(i) ), "" )
Next i
REM Cut the resulting sentence at length...
If iMaxLength > 0 Then strDefaultName = Left( strDefaultName, iMaxLength )
REM **** NB. The resulting filename is still not guaranteed to be a valid filename.
REM **** Yet it will be presented as initial filename in the following dialog:
Dim aURL() : aURL = FileSaveDialog_Simple( oDoc, "TITLE", "", strDefaultName )
If uBound( aURL ) > -1 Then oDoc.storeAsURL( aURL(0), Array() )
End If
End Sub
Function cutStringAtMarks( sStringToCut As String, aCutMarks(), Optional bExclude ) As String
REM Returns the Left portion of <sStringToCut> up to the first encountered cutMark in the array <aCutMarks>.
REM <bExclude> : Default=<True>=exclude the cutMark; Pass <False> to include it.
If IsMissing( bExclude ) Then bExclude = True
Dim i As Integer, lPos as Long, sCutMark As String
Dim sString As String : sString = sStringToCut
For i = 0 To uBound( aCutMarks )
sCutMark = aCutMarks( i )
lPos = InStr( 1, sString, sCutMark, 0 )
If lPos > 0 Then
If bExclude Then sString = Left( sString, lPos - 1 ) Else sString = Left( sString, lPos + Len( sCutMark ) - 1 )
End If
Next i
cutStringAtMarks = sString
End Function
Function FileSaveDialog_Simple( oDoc As Object, Optional strTitle, Optional strDisplayDirectory, Optional strDefaultName, Optional aFilters(), Optional bRemote ) As Variant
REM Displays a FilePicker "Save As" dialog with optional Dialog Title, Initial Folder Path, Initial File Name, Export Filters, Remote Save Location,
REM <oDoc> : The Document to be saved.
REM <strTitle> : String to be shown in the dialog Title bar.
REM <strDisplayDirectory>: Path to a Folder whose contents will be shown when the dialog opens.
REM <strDefaultName>: String to be shown in the File Name Textbox when the dialog opens.
REM <aFilters> : Array of com.sun.star.beans.StringPair describing the Export Filters to be included in the dialog.
REM These Filters should all have the EXPORT flag set.
REM Per StringPair: First = FilterName (e.g. "Jpeg Files"), Second = Extensions (e.g. "*.jpg").
REM <bRemote> : Boolean indicating whether to display the Remote FilePicker for storing the file at a remote location, e.g. via FTP.
REM Returns: an Array containing the URL of the selected file, if the user has clicked on the Save button.
REM If the user has cancelled, this Function returns an Empty Array.
If IsNull( oDoc ) Then Exit Function REM No Document passed.
REM First determine whether to use the Remote FilePicker, the System FilePicker, or the LibreOffice FilePicker.
Dim aProps(1) As New com.sun.star.beans.PropertyValue
aProps(0).Name = "nodepath"
aProps(0).Value = "/org.openoffice.Office.Common/Misc/"
aProps(1).Name = "enableasync"
aProps(1).Value = False
Dim oConfig As Object : oConfig = createUnoService( "com.sun.star.configuration.ConfigurationProvider" )
Dim oAccess As Object
oAccess = oConfig.createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", aProps() )
Dim bUseSystemDialogs As Boolean REM Corresponds (inversely) to the setting in "Tools : Options : LibreOffice : General : Open/Save Dialogs : Use LibreOffice dialogs".
bUseSystemDialogs = oAccess.UseSystemFileDialog
Dim oFilePicker As Object
If IsMissing( bRemote ) Then bRemote = False
If bRemote Then
oFilePicker = createUnoService( "com.sun.star.ui.dialogs.RemoteFilePicker" )
Elseif bUseSystemDialogs Then
oFilePicker = createUnoService( "com.sun.star.ui.dialogs.FilePicker" )
Else
oFilePicker = createUnoService( "com.sun.star.ui.dialogs.OfficeFilePicker" )
End If
REM Initialize the "Save As" Dialog with default UIMode = 10 ( auto extension ).
Dim iUIMode As Integer : iUIMode = 10
oFilePicker.initialize( Array( iUIMode ) )
If IsMissing( strTitle ) Then strTitle = "Save As:"
oFilePicker.setTitle( strTitle )
If Not IsMissing( strDisplayDirectory ) And FileExists( strDisplayDirectory ) Then
oFilePicker.setDisplayDirectory( ConvertToURL( strDisplayDirectory ) )
End If
If Not IsMissing( strDefaultName ) Then oFilePicker.setDefaultName( strDefaultName )
REM Append Export Filters.
REM Default filter "All Formats" is added automatically in the System FilePicker (on Ubuntu 17.10);
Const sFilterNameAllFormats = "All Formats" REM Add it also in the LibreOffice FilePicker :
If Not bRemote Or bUseSystemDialogs Then oFilePicker.appendFilter( sFilterNameAllFormats, "*.*" )
If Not IsMissing( aFilters ) And IsArray( aFilters ) Then
oFilePicker.appendFilterGroup( "Export Filters", aFilters ) REM Group Title is not shown.
End If
Dim iResult as Integer : iResult = oFilePicker.execute() REM Execute the "Save As" Dialog.
If iResult = com.sun.star.ui.dialogs.ExecutableDialogResults.OK Then REM The User has clicked the Save button:
REM At this stage the User has also clicked the Overwrite button if a file with the same name already exists.
Dim aFiles() As String : aFiles = oFilePicker.getSelectedFiles()
If uBound( aFiles ) > -1 Then REM We have a URL ... Else something is wrong here.
FileSaveDialog_Simple = aFiles() REM to save, call: oDoc.storeAsUrl( sURL, aSaveProps )
End If
Else REM User Cancelled.
FileSaveDialog_Simple = Array()
End If
oFilePicker.dispose
End Function
With Regards,
lib