summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2018-02-28 22:39:30 +0100
committerEike Rathke <erack@redhat.com>2018-03-01 13:16:56 +0100
commit66564dac88ffcc781b4fade7ca0f4f72af6b8bca (patch)
tree8214347cd6fe0beb19f1ae60f2fb24e2460663fa
parent18b4c1d0b8e030e4fa081995eccf68f01049892e (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.hxx4
-rw-r--r--sc/source/filter/oox/excelfilter.cxx71
-rw-r--r--sc/source/filter/oox/sheetdatacontext.cxx21
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