diff options
author | Eike Rathke <erack@redhat.com> | 2018-02-28 22:39:30 +0100 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2018-03-01 13:16:56 +0100 |
commit | 66564dac88ffcc781b4fade7ca0f4f72af6b8bca (patch) | |
tree | 8214347cd6fe0beb19f1ae60f2fb24e2460663fa | |
parent | 18b4c1d0b8e030e4fa081995eccf68f01049892e (diff) |
Resolves: tdf#114555 check .xlsx col/row/tab overflow and display warning
Change-Id: I3091a890b6d4a3f27d9284fc5c0e2df3bc8ce527
Reviewed-on: https://gerrit.libreoffice.org/50541
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Eike Rathke <erack@redhat.com>
-rw-r--r-- | sc/source/filter/inc/addressconverter.hxx | 4 | ||||
-rw-r--r-- | sc/source/filter/oox/excelfilter.cxx | 71 | ||||
-rw-r--r-- | sc/source/filter/oox/sheetdatacontext.cxx | 21 |
3 files changed, 90 insertions, 6 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 989befcb6b51..006c4818e48a 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/svapp.hxx> +#include <vcl/weld.hxx> +#include <svtools/sfxecode.hxx> +#include <tools/urlobj.hxx> + namespace oox { namespace xls { @@ -97,9 +106,67 @@ 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, RID_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? */ + + vcl::Window* pWin = ScDocShell::GetActiveDialogParent(); + std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr, + VclMessageType::Warning, VclButtonsType::Ok, + aWarning)); + xWarn->run(); + } + } + } + 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 |