diff options
author | Eike Rathke <erack@redhat.com> | 2018-02-28 22:39:30 +0100 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2018-03-28 23:51:57 +0200 |
commit | 828e41a91742a55f213c1c9cd93efa4cf73bdf3c (patch) | |
tree | e1d91873720bf5158707668895edb0f5eb7655ac | |
parent | 465df8ea64b417d02917b2f1ca99f502e8e1c6e8 (diff) |
Resolves: tdf#114555 check .xlsx col/row/tab overflow and display warning
This is a combination of 2 commits.
Resolves: tdf#114555 check .xlsx col/row/tab overflow and display warning
Cherry-picked from 66564dac88ffcc781b4fade7ca0f4f72af6b8bca and
backported / un-weld-ed by using the original patch set
https://gerrit.libreoffice.org/#/c/50541/1 before weld-ing, and
getRID_ERRCTX() instead of RID_ERRCTX.
Related: tdf#114555 cater for lastcolumn+1 oddity if last is last possible
Else our own saved .xlsx files raise the excess columns warning.
(cherry picked from commit ccc977ba10b61108a56e00a79c0f7a1517e026cc)
e1791dd026d9faf4b391ad34da43ec0c70c8de83
Change-Id: I3091a890b6d4a3f27d9284fc5c0e2df3bc8ce527
Reviewed-on: https://gerrit.libreoffice.org/50570
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Bartosz Kosiorek <gang65@poczta.onet.pl>
(cherry picked from commit 621634923ab7c11ceef9757c481f92977ef863f6)
Reviewed-on: https://gerrit.libreoffice.org/51384
Reviewed-by: Kohei Yoshida <libreoffice@kohei.us>
Reviewed-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
Tested-by: Markus Mohrhard <markus.mohrhard@googlemail.com>
-rw-r--r-- | sc/source/filter/inc/addressconverter.hxx | 4 | ||||
-rw-r--r-- | sc/source/filter/oox/excelfilter.cxx | 69 | ||||
-rw-r--r-- | sc/source/filter/oox/sheetdatacontext.cxx | 21 | ||||
-rw-r--r-- | sc/source/filter/oox/worksheethelper.cxx | 10 |
4 files changed, 96 insertions, 8 deletions
diff --git a/sc/source/filter/inc/addressconverter.hxx b/sc/source/filter/inc/addressconverter.hxx index 57f1f33cabcd..d1d53531e0f1 100644 --- a/sc/source/filter/inc/addressconverter.hxx +++ b/sc/source/filter/inc/addressconverter.hxx @@ -479,6 +479,10 @@ public: static css::uno::Sequence<css::table::CellRangeAddress> toApiSequence(const ScRangeList& orRanges); + bool isColOverflow() const { return mbColOverflow; } + bool isRowOverflow() const { return mbRowOverflow; } + bool isTabOverflow() const { return mbTabOverflow; } + private: void initializeMaxPos( sal_Int16 nMaxXlsTab, sal_Int32 nMaxXlsCol, sal_Int32 nMaxXlsRow ); diff --git a/sc/source/filter/oox/excelfilter.cxx b/sc/source/filter/oox/excelfilter.cxx index 171f5ff67cf7..55cee4841b7f 100644 --- a/sc/source/filter/oox/excelfilter.cxx +++ b/sc/source/filter/oox/excelfilter.cxx @@ -30,6 +30,15 @@ #include <workbookfragment.hxx> #include <xestream.hxx> +#include <addressconverter.hxx> +#include <document.hxx> +#include <docsh.hxx> +#include <scerrors.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/vclptr.hxx> +#include <svtools/sfxecode.hxx> +#include <tools/urlobj.hxx> + namespace oox { namespace xls { @@ -97,9 +106,65 @@ bool ExcelFilter::importDocument() the class WorkbookHelper, and execute the import filter by constructing an instance of WorkbookFragment and loading the file. */ WorkbookGlobalsRef xBookGlob(WorkbookHelper::constructGlobals(*this)); - if (xBookGlob.get() && importFragment(new WorkbookFragment(*xBookGlob, aWorkbookPath))) + if (xBookGlob.get()) { - return true; + rtl::Reference<FragmentHandler> xWorkbookFragment( new WorkbookFragment(*xBookGlob, aWorkbookPath)); + bool bRet = importFragment( xWorkbookFragment); + if (bRet) + { + const WorkbookFragment* pWF = static_cast<const WorkbookFragment*>(xWorkbookFragment.get()); + const AddressConverter& rAC = pWF->getAddressConverter(); + if (rAC.isTabOverflow() || rAC.isColOverflow() || rAC.isRowOverflow()) + { + const ScDocument& rDoc = pWF->getScDocument(); + if (rDoc.IsUserInteractionEnabled()) + { + // Show data loss warning. + + INetURLObject aURL( getFileUrl()); + SfxErrorContext aContext( ERRCTX_SFX_OPENDOC, + aURL.getName( INetURLObject::LAST_SEGMENT, true, + INetURLObject::DecodeMechanism::WithCharset), + nullptr, getRID_ERRCTX()); + + OUString aWarning; + aContext.GetString( ERRCODE_NONE.MakeWarning(), aWarning); + aWarning += ":\n"; + + OUString aMsg; + if (rAC.isTabOverflow()) + { + if (ErrorHandler::GetErrorString( SCWARN_IMPORT_SHEET_OVERFLOW, aMsg)) + aWarning += aMsg; + } + if (rAC.isColOverflow()) + { + if (!aMsg.isEmpty()) + aWarning += "\n"; + if (ErrorHandler::GetErrorString( SCWARN_IMPORT_COLUMN_OVERFLOW, aMsg)) + aWarning += aMsg; + } + if (rAC.isRowOverflow()) + { + if (!aMsg.isEmpty()) + aWarning += "\n"; + if (ErrorHandler::GetErrorString( SCWARN_IMPORT_ROW_OVERFLOW, aMsg)) + aWarning += aMsg; + } + + /* XXX displaying a dialog here is ugly and should + * rather happen at UI level instead of at the filter + * level, but it seems there's no way to transport + * detailed information other than returning true or + * false at this point? */ + + ScopedVclPtrInstance<WarningBox> pBox( ScDocShell::GetActiveDialogParent(), + MessBoxStyle::Ok | MessBoxStyle::DefaultOk, aWarning); + pBox->Execute(); + } + } + } + return bRet; } } catch (...) diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx index b221cb16a73b..5f17d8c419b6 100644 --- a/sc/source/filter/oox/sheetdatacontext.cxx +++ b/sc/source/filter/oox/sheetdatacontext.cxx @@ -273,6 +273,7 @@ void SheetDataContext::importRow( const AttributeList& rAttribs ) } else aModel.mnRow = ++mnRow; + mrAddressConv.checkRow( mnRow, true); mnCol = -1; aModel.mfHeight = rAttribs.getDouble( XML_ht, -1.0 ); @@ -297,8 +298,14 @@ void SheetDataContext::importRow( const AttributeList& rAttribs ) if( (0 < nSepPos) && (nSepPos + 1 < aColSpanToken.getLength()) ) { // OOXML uses 1-based integer column indexes, row model expects 0-based colspans - sal_Int32 nLastCol = ::std::min( aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1, nMaxCol ); - aModel.insertColSpan( ValueRange( aColSpanToken.copy( 0, nSepPos ).toInt32() - 1, nLastCol ) ); + const sal_Int32 nCol1 = aColSpanToken.copy( 0, nSepPos ).toInt32() - 1; + const bool bValid1 = mrAddressConv.checkCol( nCol1, true); + if (bValid1) + { + const sal_Int32 nCol2 = aColSpanToken.copy( nSepPos + 1 ).toInt32() - 1; + mrAddressConv.checkCol( nCol2, true); + aModel.insertColSpan( ValueRange( nCol1, ::std::min( nCol2, nMaxCol ))); + } } } @@ -314,7 +321,9 @@ bool SheetDataContext::importCell( const AttributeList& rAttribs ) if (!p) { ++mnCol; - maCellData.maCellAddr = ScAddress( mnCol, mnRow, mnSheet ); + ScAddress aAddress( mnCol, mnRow, mnSheet ); + bValid = mrAddressConv.checkCellAddress( aAddress, true ); + maCellData.maCellAddr = aAddress; } else { @@ -374,6 +383,7 @@ void SheetDataContext::importRow( SequenceInputStream& rStrm ) nSpanCount = rStrm.readInt32(); maCurrPos.mnCol = 0; + mrAddressConv.checkRow( maCurrPos.mnRow, true); // row index is 0-based in BIFF12, but RowModel expects 1-based aModel.mnRow = maCurrPos.mnRow + 1; // row height is in twips in BIFF12, convert to points @@ -393,8 +403,11 @@ void SheetDataContext::importRow( SequenceInputStream& rStrm ) { sal_Int32 nFirstCol, nLastCol; nFirstCol = rStrm.readInt32(); + const bool bValid1 = mrAddressConv.checkCol( nFirstCol, true); nLastCol = rStrm.readInt32(); - aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) ); + mrAddressConv.checkCol( nLastCol, true); + if (bValid1) + aModel.insertColSpan( ValueRange( nFirstCol, ::std::min( nLastCol, nMaxCol ) ) ); } // set row properties in the current sheet diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx index 2ef765d932b5..c1cdae73e4b1 100644 --- a/sc/source/filter/oox/worksheethelper.cxx +++ b/sc/source/filter/oox/worksheethelper.cxx @@ -763,8 +763,14 @@ void WorksheetGlobals::setColumnModel( const ColumnModel& rModel ) sal_Int32 nLastCol = rModel.maRange.mnLast - 1; if( getAddressConverter().checkCol( nFirstCol, true ) && (nFirstCol <= nLastCol) ) { - // validate last column index - if( !getAddressConverter().checkCol( nLastCol, true ) ) + // Validate last column index. + // If last column is equal to last possible column, Excel adds one + // more. We do that also in XclExpColinfo::SaveXml() and for 1024 end + // up with 1025 instead, which would lead to excess columns in + // checkCol(). Cater for this oddity. + if (nLastCol == mrMaxApiPos.Col() + 1) + --nLastCol; + else if( !getAddressConverter().checkCol( nLastCol, true ) ) nLastCol = mrMaxApiPos.Col(); // try to find entry in column model map that is able to merge with the passed model bool bInsertModel = true; |