XLSX: Importing tables with power query connections
If a table type is "queryTable", Excel might remove table data from the sheet based on `removeDataOnSave` attribute. In those cases, when we export the table to XLSX, we write empty column headers, which Excel doesn't accept. bug-doc: forum-es-7685.xlsx Change-Id: Ia05dda91c0806271e1846e1512328950a048ff28 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/203050 Reviewed-by: Michael Stahl <michael.stahl@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> (cherry picked from commit fa2cbdb84ad571379c183f76e66c12920e787f4d) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/204433 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
bf7bd37d1c
commit
66081b8f71
Binary file not shown.
@@ -87,6 +87,18 @@ CPPUNIT_TEST_FIXTURE(ScExportTest5, testInvalidNamedRange)
|
||||
CPPUNIT_ASSERT(!xNamedRanges->hasByName(u"myname"_ustr));
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(ScExportTest5, testQueryTableHeaders)
|
||||
{
|
||||
createScDoc("xlsx/TableEmptyHeaders.xlsx");
|
||||
save(TestFilter::XLSX);
|
||||
|
||||
xmlDocUniquePtr pTable = parseExport(u"xl/tables/table1.xml"_ustr);
|
||||
CPPUNIT_ASSERT(pTable);
|
||||
|
||||
assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[1]", "name", u"Column1");
|
||||
assertXPath(pTable, "/x:table/x:tableColumns/x:tableColumn[2]", "name", u"Column2");
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(ScExportTest5, testExternalDefinedNameXLSX)
|
||||
{
|
||||
createScDoc("xlsx/tdf144397.xlsx");
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
TableColumn& createTableColumn();
|
||||
|
||||
/** Applies the columns to the passed database range. */
|
||||
bool finalizeImport( ScDBData* pDBData );
|
||||
bool finalizeImport( ScDBData* pDBData, bool bQueryTable );
|
||||
|
||||
private:
|
||||
typedef RefVector< TableColumn > TableColumnVector;
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
TableColumns& createTableColumns();
|
||||
|
||||
/** Applies the table columns to the passed database range. */
|
||||
void finalizeImport( ScDBData* pDBData );
|
||||
void finalizeImport( ScDBData* pDBData, bool bQueryTable );
|
||||
|
||||
private:
|
||||
/** Returns the table columns object used. */
|
||||
|
||||
@@ -200,7 +200,8 @@ void Table::applyAutoFilters()
|
||||
|
||||
void Table::applyTableColumns()
|
||||
{
|
||||
maTableColumns.finalizeImport( findDatabaseRangeByIndex( mnTokenIndex ));
|
||||
maTableColumns.finalizeImport(findDatabaseRangeByIndex(mnTokenIndex),
|
||||
maModel.mnType == XML_queryTable);
|
||||
}
|
||||
|
||||
TableBuffer::TableBuffer( const WorkbookHelper& rHelper ) :
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <oox/helper/attributelist.hxx>
|
||||
#include <oox/token/tokens.hxx>
|
||||
#include <dbdata.hxx>
|
||||
#include <document.hxx>
|
||||
#include <subtotalparam.hxx>
|
||||
|
||||
XmlColumnPrModel::XmlColumnPrModel() :
|
||||
@@ -136,7 +137,7 @@ TableColumn& TableColumns::createTableColumn()
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
bool TableColumns::finalizeImport( ScDBData* pDBData )
|
||||
bool TableColumns::finalizeImport( ScDBData* pDBData, bool bQueryTable )
|
||||
{
|
||||
SAL_WARN_IF( static_cast<size_t>(mnCount) != maTableColumnVector.size(), "sc.filter",
|
||||
"TableColumns::finalizeImport - count attribute doesn't match number of tableColumn elements");
|
||||
@@ -167,6 +168,27 @@ bool TableColumns::finalizeImport( ScDBData* pDBData )
|
||||
}
|
||||
pDBData->SetTableColumnNames( std::move(aNames) );
|
||||
|
||||
// If table type is "queryTable" and `removeDataOnSave` attribute is set to true,
|
||||
// Excel removes table data from sheet including headers
|
||||
// We don't support Power Query connections, fill table headers in the sheet with table data.
|
||||
if (bQueryTable && pDBData->HasHeader())
|
||||
{
|
||||
ScRange aRange;
|
||||
pDBData->GetArea(aRange);
|
||||
ScDocument& rDoc = getScDocument();
|
||||
const std::vector<OUString>& rNames = pDBData->GetTableColumnNames();
|
||||
SCCOL nStartCol = aRange.aStart.Col();
|
||||
SCROW nRow = aRange.aStart.Row();
|
||||
SCTAB nTab = aRange.aStart.Tab();
|
||||
for (size_t j = 0; j < rNames.size(); ++j)
|
||||
{
|
||||
SCCOL nCol = nStartCol + static_cast<SCCOL>(j);
|
||||
OUString sHeader = rNames[j];
|
||||
if (!sHeader.isEmpty() && rDoc.GetString(nCol, nRow, nTab).isEmpty())
|
||||
rDoc.SetString(nCol, nRow, nTab, sHeader);
|
||||
}
|
||||
}
|
||||
|
||||
// Import subtotal parameters for columns
|
||||
if (hasAnySetValue)
|
||||
{
|
||||
@@ -194,11 +216,11 @@ TableColumns& TableColumnsBuffer::createTableColumns()
|
||||
return *xTableColumns;
|
||||
}
|
||||
|
||||
void TableColumnsBuffer::finalizeImport( ScDBData* pDBData )
|
||||
void TableColumnsBuffer::finalizeImport( ScDBData* pDBData, bool bQueryTable )
|
||||
{
|
||||
TableColumns* pTableColumns = getActiveTableColumns();
|
||||
if ( pTableColumns )
|
||||
pTableColumns->finalizeImport( pDBData );
|
||||
pTableColumns->finalizeImport( pDBData, bQueryTable );
|
||||
}
|
||||
|
||||
TableColumns* TableColumnsBuffer::getActiveTableColumns()
|
||||
|
||||
Reference in New Issue
Block a user