diff options
author | Caolán McNamara <caolanm@redhat.com> | 2021-07-13 12:38:07 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2021-07-14 20:37:33 +0200 |
commit | b8903bc106dad036acb3d117e5c4fc955697fe02 (patch) | |
tree | 32bdf93bee8da8e876f02932968fb17e4c92c079 | |
parent | 6c94eeb92fa0ea14814175276f35a25512cc6f2b (diff) |
rhbz#1980800 allow --convert-to csv to write each sheet to a separate file
Related: tdf#135762 except only currently implemented for command line use
sample usage:
soffice --convert-to csv:"Text - txt - csv (StarCalc)":44,34,UTF8,1,,0,false,true,false,false,false,-1 sample.ods
where the new (11th!) final token ("-1") enables writing each sheet to a
new file based on the suggested target name so output in this example
is files sample-Sheet1.csv and sample-Sheet2.csv
Only -1 for 'all sheets' vs 0 for existing 'current sheet only' (which
is always sheet 0 from the command line) are currently options but the
token could be expanded in the future to select specific sheets to
export.
Change-Id: Ib99a120f1a2c8d1008a7a3c59a6b39f572fb346e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118850
Tested-by: Jenkins
Reviewed-by: Eike Rathke <erack@redhat.com>
-rw-r--r-- | desktop/source/app/dispatchwatcher.cxx | 26 | ||||
-rw-r--r-- | sc/source/ui/dbgui/imoptdlg.cxx | 7 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh.cxx | 97 | ||||
-rw-r--r-- | sc/source/ui/inc/docsh.hxx | 2 | ||||
-rw-r--r-- | sc/source/ui/inc/imoptdlg.hxx | 6 |
5 files changed, 106 insertions, 32 deletions
diff --git a/desktop/source/app/dispatchwatcher.cxx b/desktop/source/app/dispatchwatcher.cxx index a2e79d8283ae..8541c273cc83 100644 --- a/desktop/source/app/dispatchwatcher.cxx +++ b/desktop/source/app/dispatchwatcher.cxx @@ -30,6 +30,7 @@ #include "officeipcthread.hxx" #include <rtl/ustring.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/string.hxx> #include <comphelper/synchronousdispatch.hxx> #include <com/sun/star/io/IOException.hpp> #include <com/sun/star/util/XCloseable.hpp> @@ -598,6 +599,8 @@ bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest aFilter = impl_GuessFilter( aOutFile, aDocService ); } + bool bMultiFileTarget = false; + if (aFilter.isEmpty()) { std::cerr << "Error: no export filter" << std::endl; @@ -616,10 +619,23 @@ bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest conversionProperties[1].Name = "FilterName"; if( 0 < nFilterOptionsIndex ) { - conversionProperties[1].Value <<= aFilter.copy(0, nFilterOptionsIndex); + OUString sFilterName = aFilter.copy(0, nFilterOptionsIndex); + OUString sFilterOptions = aFilter.copy(nFilterOptionsIndex + 1); + + if (sFilterName == "Text - txt - csv (StarCalc)") + { + sal_Int32 nIdx(0); + // If the 11th token token is '-1' then we export a file + // per sheet where the file name is based on the suggested + // output filename concatenated with the sheet name, so adjust + // the output and overwrite messages + bMultiFileTarget = sFilterOptions.getToken(11, ',', nIdx) == "-1"; + } + + conversionProperties[1].Value <<= sFilterName; conversionProperties[2].Name = "FilterOptions"; - conversionProperties[2].Value <<= aFilter.copy(nFilterOptionsIndex + 1); + conversionProperties[2].Value <<= sFilterOptions; } else { @@ -639,9 +655,11 @@ bool DispatchWatcher::executeDispatchRequests( const std::vector<DispatchRequest OString aTargetURL8 = OUStringToOString(aTempName, osl_getThreadTextEncoding()); if (aDispatchRequest.aRequestType != REQUEST_CAT) { - std::cout << "convert " << aSource8 << " -> " << aTargetURL8; + std::cout << "convert " << aSource8; + if (!bMultiFileTarget) + std::cout << " -> " << aTargetURL8; std::cout << " using filter : " << OUStringToOString(aFilter, osl_getThreadTextEncoding()) << std::endl; - if (FStatHelper::IsDocument(aOutFile)) + if (!bMultiFileTarget && FStatHelper::IsDocument(aOutFile)) std::cout << "Overwriting: " << OUStringToOString(aTempName, osl_getThreadTextEncoding()) << std::endl ; } try diff --git a/sc/source/ui/dbgui/imoptdlg.cxx b/sc/source/ui/dbgui/imoptdlg.cxx index 071f1b0257bc..d8c4fd810ea3 100644 --- a/sc/source/ui/dbgui/imoptdlg.cxx +++ b/sc/source/ui/dbgui/imoptdlg.cxx @@ -43,6 +43,7 @@ ScImportOptions::ScImportOptions( const OUString& rStr ) bSaveNumberAsSuch = true; bSaveFormulas = false; bRemoveSpace = false; + bNewFilePerSheet = false; sal_Int32 nTokenCount = comphelper::string::getTokenCount(rStr, ','); if ( nTokenCount < 3 ) return; @@ -77,6 +78,8 @@ ScImportOptions::ScImportOptions( const OUString& rStr ) bSaveFormulas = rStr.getToken(0, ',', nIdx) == "true"; if ( nTokenCount >= 11 ) bRemoveSpace = rStr.getToken(0, ',', nIdx) == "true"; + if ( nTokenCount >= 12 ) + bNewFilePerSheet = rStr.getToken(0, ',', nIdx) == "-1"; } } @@ -99,7 +102,9 @@ OUString ScImportOptions::BuildString() const "," + OUString::boolean( bSaveFormulas ) + // "save formulas": not in ScAsciiOptions "," + - OUString::boolean( bRemoveSpace ); // same as "Remove space" in ScAsciiOptions + OUString::boolean( bRemoveSpace ) + // same as "Remove space" in ScAsciiOptions + "," + + std::u16string_view(bNewFilePerSheet ? u"-1" : u"0") ; // Only available for command line --convert-to return aResult; } diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 055f2fdf727a..873e5c598bab 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -44,6 +44,7 @@ #include <sfx2/objface.hxx> #include <sfx2/viewfrm.hxx> #include <svl/documentlockfile.hxx> +#include <svl/fstathelper.hxx> #include <svl/sharecontrolfile.hxx> #include <svl/urihelper.hxx> #include <osl/file.hxx> @@ -120,6 +121,7 @@ #include <comphelper/processfactory.hxx> #include <comphelper/string.hxx> #include <unotools/configmgr.hxx> +#include <unotools/ucbstreamhelper.hxx> #include <uiitems.hxx> #include <dpobject.hxx> #include <markdata.hxx> @@ -1926,7 +1928,7 @@ void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr) } -void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt ) +void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt, SCTAB nTab ) { sal_Unicode cDelim = rAsciiOpt.nFieldSepCode; sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode; @@ -1972,7 +1974,6 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt SCCOL nStartCol = 0; SCROW nStartRow = 0; - SCTAB nTab = GetSaveTab(); SCCOL nEndCol; SCROW nEndRow; m_aDocument.GetCellArea( nTab, nEndCol, nEndRow ); @@ -2390,35 +2391,81 @@ bool ScDocShell::ConvertTo( SfxMedium &rMed ) } else if (aFltName == pFilterAscii) { - SvStream* pStream = rMed.GetOutStream(); - if (pStream) + OUString sItStr; + SfxItemSet* pSet = rMed.GetItemSet(); + const SfxPoolItem* pItem; + if ( pSet && SfxItemState::SET == + pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) ) { - OUString sItStr; - SfxItemSet* pSet = rMed.GetItemSet(); - const SfxPoolItem* pItem; - if ( pSet && SfxItemState::SET == - pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) ) - { - sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); - } + sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue(); + } - if ( sItStr.isEmpty() ) - { - // default for ascii export (from API without options): - // ISO8859-1/MS_1252 encoding, comma, double quotes + if ( sItStr.isEmpty() ) + { + // default for ascii export (from API without options): + // ISO8859-1/MS_1252 encoding, comma, double quotes - ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 ); - sItStr = aDefOptions.BuildString(); - } + ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 ); + sItStr = aDefOptions.BuildString(); + } - weld::WaitObject aWait( GetActiveDialogParent() ); - ScImportOptions aOptions( sItStr ); - AsciiSave( *pStream, aOptions ); + weld::WaitObject aWait( GetActiveDialogParent() ); + ScImportOptions aOptions( sItStr ); + + if (aOptions.bNewFilePerSheet) + { bRet = true; - if (m_aDocument.GetTableCount() > 1) - if (!rMed.GetError()) - rMed.SetError(SCWARN_EXPORT_ASCII); + INetURLObject aURLObject(rMed.GetURLObject()); + OUString sExt = aURLObject.CutExtension(); + OUString sBaseName = aURLObject.GetLastName(); + aURLObject.CutLastName(); + + for (SCTAB i = 0, nCount = m_aDocument.GetTableCount(); i < nCount; ++i) + { + OUString sTabName; + if (!m_aDocument.GetName(i, sTabName)) + sTabName = OUString::number(i); + INetURLObject aSheetURLObject(aURLObject); + OUString sFileName = sBaseName + "-" + sTabName; + if (!sExt.isEmpty()) + sFileName = sFileName + "." + sExt; + aSheetURLObject.Append(sFileName); + + // log similar to DispatchWatcher::executeDispatchRequests + OUString aOutFile = aSheetURLObject.GetMainURL(INetURLObject::DecodeMechanism::NONE); + OUString aDisplayedName; + if (osl::FileBase::E_None != osl::FileBase::getSystemPathFromFileURL(aOutFile, aDisplayedName)) + aDisplayedName = aOutFile; + std::cout << "Writing sheet " << OUStringToOString(sTabName, osl_getThreadTextEncoding()) << " -> " + << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) + << std::endl; + + if (FStatHelper::IsDocument(aOutFile)) + std::cout << "Overwriting: " << OUStringToOString(aDisplayedName, osl_getThreadTextEncoding()) << std::endl ; + + std::unique_ptr<SvStream> xStm = ::utl::UcbStreamHelper::CreateStream(aOutFile, StreamMode::TRUNC | StreamMode::WRITE); + if (!xStm) + { + SetError(SCERR_IMPORT_UNKNOWN); + bRet = false; + break; + } + AsciiSave(*xStm, aOptions, i); + } + } + else + { + SvStream* pStream = rMed.GetOutStream(); + if (pStream) + { + AsciiSave(*pStream, aOptions, GetSaveTab()); + bRet = true; + + if (m_aDocument.GetTableCount() > 1) + if (!rMed.GetError()) + rMed.SetError(SCWARN_EXPORT_ASCII); + } } } else if (aFltName == pFilterDBase) diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index 3a6366699b52..eb6203362110 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -227,7 +227,7 @@ public: ScDrawLayer* MakeDrawLayer(); - void AsciiSave( SvStream& rStream, const ScImportOptions& rOpt ); + void AsciiSave( SvStream& rStream, const ScImportOptions& rOpt, SCTAB nTab ); void Execute( SfxRequest& rReq ); void GetState( SfxItemSet &rSet ); diff --git a/sc/source/ui/inc/imoptdlg.hxx b/sc/source/ui/inc/imoptdlg.hxx index c162da6d7740..2314349f602a 100644 --- a/sc/source/ui/inc/imoptdlg.hxx +++ b/sc/source/ui/inc/imoptdlg.hxx @@ -31,7 +31,8 @@ public: ScImportOptions( sal_Unicode nFieldSep, sal_Unicode nTextSep, rtl_TextEncoding nEnc ) : nFieldSepCode(nFieldSep), nTextSepCode(nTextSep), bFixedWidth(false), bSaveAsShown(false), bQuoteAllText(false), - bSaveNumberAsSuch(true), bSaveFormulas(false), bRemoveSpace(false) + bSaveNumberAsSuch(true), bSaveFormulas(false), bRemoveSpace(false), + bNewFilePerSheet(false) { SetTextEncoding( nEnc ); } ScImportOptions& operator=( const ScImportOptions& rCpy ) = default; @@ -50,6 +51,9 @@ public: bool bSaveNumberAsSuch; bool bSaveFormulas; bool bRemoveSpace; + // currently only "0" for 'current sheet' and "-1" for all sheets (each to + // a separate file) are options + bool bNewFilePerSheet; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |