Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / sc / source / filter / oox / querytablebuffer.cxx
blobbc09a62754f6b54e470a077d4d98f566400f8d9f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "querytablebuffer.hxx"
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/sheet/XAreaLink.hpp>
25 #include <com/sun/star/sheet/XAreaLinks.hpp>
26 #include <osl/diagnose.h>
27 #include <oox/core/filterbase.hxx>
28 #include <oox/helper/attributelist.hxx>
29 #include <oox/token/properties.hxx>
30 #include <oox/token/tokens.hxx>
31 #include "addressconverter.hxx"
32 #include "biffinputstream.hxx"
33 #include "connectionsbuffer.hxx"
34 #include "defnamesbuffer.hxx"
36 namespace oox {
37 namespace xls {
39 using namespace ::com::sun::star::container;
40 using namespace ::com::sun::star::sheet;
41 using namespace ::com::sun::star::table;
42 using namespace ::com::sun::star::uno;
44 namespace {
46 const sal_uInt32 BIFF12_QUERYTABLE_HEADERS = 0x00000001;
47 const sal_uInt32 BIFF12_QUERYTABLE_ROWNUMBERS = 0x00000002;
48 const sal_uInt32 BIFF12_QUERYTABLE_DISABLEREFRESH = 0x00000004;
49 const sal_uInt32 BIFF12_QUERYTABLE_BACKGROUND = 0x00000008;
50 const sal_uInt32 BIFF12_QUERYTABLE_FIRSTBACKGROUND = 0x00000010;
51 const sal_uInt32 BIFF12_QUERYTABLE_REFRESHONLOAD = 0x00000020;
52 const sal_uInt32 BIFF12_QUERYTABLE_FILLFORMULAS = 0x00000100;
53 const sal_uInt32 BIFF12_QUERYTABLE_SAVEDATA = 0x00000200;
54 const sal_uInt32 BIFF12_QUERYTABLE_DISABLEEDIT = 0x00000400;
55 const sal_uInt32 BIFF12_QUERYTABLE_PRESERVEFORMAT = 0x00000800;
56 const sal_uInt32 BIFF12_QUERYTABLE_ADJUSTCOLWIDTH = 0x00001000;
57 const sal_uInt32 BIFF12_QUERYTABLE_INTERMEDIATE = 0x00002000;
58 const sal_uInt32 BIFF12_QUERYTABLE_APPLYNUMFMT = 0x00004000;
59 const sal_uInt32 BIFF12_QUERYTABLE_APPLYFONT = 0x00008000;
60 const sal_uInt32 BIFF12_QUERYTABLE_APPLYALIGNMENT = 0x00010000;
61 const sal_uInt32 BIFF12_QUERYTABLE_APPLYBORDER = 0x00020000;
62 const sal_uInt32 BIFF12_QUERYTABLE_APPLYFILL = 0x00040000;
63 const sal_uInt32 BIFF12_QUERYTABLE_APPLYPROTECTION = 0x00080000;
65 void lclAppendWebQueryTableName( OUStringBuffer& rTables, const OUString& rTableName )
67 if( !rTableName.isEmpty() )
69 if( !rTables.isEmpty() )
70 rTables.append( ';' );
71 rTables.append( "HTML__" ).append( rTableName );
75 void lclAppendWebQueryTableIndex( OUStringBuffer& rTables, sal_Int32 nTableIndex )
77 if( nTableIndex > 0 )
79 if( !rTables.isEmpty() )
80 rTables.append( ';' );
81 rTables.append( "HTML_" ).append( nTableIndex );
85 OUString lclBuildWebQueryTables( const WebPrModel::TablesVector& rTables )
87 if( rTables.empty() )
88 return OUString( "HTML_tables" );
90 OUStringBuffer aTables;
91 for( WebPrModel::TablesVector::const_iterator aIt = rTables.begin(), aEnd = rTables.end(); aIt != aEnd; ++aIt )
93 if( aIt->has< OUString >() )
94 lclAppendWebQueryTableName( aTables, aIt->get< OUString >() );
95 else if( aIt->has< sal_Int32 >() )
96 lclAppendWebQueryTableIndex( aTables, aIt->get< sal_Int32 >() );
98 return aTables.makeStringAndClear();
101 Reference< XAreaLink > lclFindAreaLink(
102 const Reference< XAreaLinks >& rxAreaLinks, const CellAddress& rDestPos,
103 const OUString& rFileUrl, const OUString& rTables, const OUString& rFilterName, const OUString& rFilterOptions )
107 Reference< XEnumerationAccess > xAreaLinksEA( rxAreaLinks, UNO_QUERY_THROW );
108 Reference< XEnumeration > xAreaLinksEnum( xAreaLinksEA->createEnumeration(), UNO_SET_THROW );
109 while( xAreaLinksEnum->hasMoreElements() )
111 Reference< XAreaLink > xAreaLink( xAreaLinksEnum->nextElement(), UNO_QUERY_THROW );
112 PropertySet aPropSet( xAreaLink );
113 CellRangeAddress aDestArea = xAreaLink->getDestArea();
114 OUString aString;
115 if( (rDestPos.Sheet == aDestArea.Sheet) && (rDestPos.Column == aDestArea.StartColumn) && (rDestPos.Row == aDestArea.StartRow) &&
116 (rTables == xAreaLink->getSourceArea()) &&
117 aPropSet.getProperty( aString, PROP_Url ) && (rFileUrl == aString) &&
118 aPropSet.getProperty( aString, PROP_Filter ) && (rFilterName == aString) &&
119 aPropSet.getProperty( aString, PROP_FilterOptions ) && (rFilterOptions == aString) )
120 return xAreaLink;
123 catch( Exception& )
126 return Reference< XAreaLink >();
129 } // namespace
131 QueryTableModel::QueryTableModel() :
132 mnConnId( -1 ),
133 mnGrowShrinkType( XML_insertDelete ),
134 mbHeaders( true ),
135 mbRowNumbers( false ),
136 mbDisableRefresh( false ),
137 mbBackground( true ),
138 mbFirstBackground( false ),
139 mbRefreshOnLoad( false ),
140 mbFillFormulas( false ),
141 mbRemoveDataOnSave( false ),
142 mbDisableEdit( false ),
143 mbPreserveFormat( true ),
144 mbAdjustColWidth( true ),
145 mbIntermediate( false )
149 QueryTable::QueryTable( const WorksheetHelper& rHelper ) :
150 WorksheetHelper( rHelper )
154 void QueryTable::importQueryTable( const AttributeList& rAttribs )
156 maModel.maDefName = rAttribs.getXString( XML_name, OUString() );
157 maModel.mnConnId = rAttribs.getInteger( XML_connectionId, -1 );
158 maModel.mnGrowShrinkType = rAttribs.getToken( XML_growShrinkType, XML_insertDelete );
159 maModel.mnAutoFormatId = rAttribs.getInteger( XML_autoFormatId, 0 );
160 maModel.mbHeaders = rAttribs.getBool( XML_headers, true );
161 maModel.mbRowNumbers = rAttribs.getBool( XML_rowNumbers, false );
162 maModel.mbDisableRefresh = rAttribs.getBool( XML_disableRefresh, false );
163 maModel.mbBackground = rAttribs.getBool( XML_backgroundRefresh, true );
164 maModel.mbFirstBackground = rAttribs.getBool( XML_firstBackgroundRefresh, false );
165 maModel.mbRefreshOnLoad = rAttribs.getBool( XML_refreshOnLoad, false );
166 maModel.mbFillFormulas = rAttribs.getBool( XML_fillFormulas, false );
167 maModel.mbRemoveDataOnSave = rAttribs.getBool( XML_removeDataOnSave, false );
168 maModel.mbDisableEdit = rAttribs.getBool( XML_disableEdit, false );
169 maModel.mbPreserveFormat = rAttribs.getBool( XML_preserveFormatting, true );
170 maModel.mbAdjustColWidth = rAttribs.getBool( XML_adjustColumnWidth, true );
171 maModel.mbIntermediate = rAttribs.getBool( XML_intermediate, false );
172 maModel.mbApplyNumFmt = rAttribs.getBool( XML_applyNumberFormats, false );
173 maModel.mbApplyFont = rAttribs.getBool( XML_applyFontFormats, false );
174 maModel.mbApplyAlignment = rAttribs.getBool( XML_applyAlignmentFormats, false );
175 maModel.mbApplyBorder = rAttribs.getBool( XML_applyBorderFormats, false );
176 maModel.mbApplyFill = rAttribs.getBool( XML_applyPatternFormats, false );
177 // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
178 maModel.mbApplyProtection = rAttribs.getBool( XML_applyWidthHeightFormats, false );
181 void QueryTable::importQueryTable( SequenceInputStream& rStrm )
183 sal_uInt32 nFlags;
184 nFlags = rStrm.readuInt32();
185 maModel.mnAutoFormatId = rStrm.readuInt16();
186 maModel.mnConnId = rStrm.readInt32();
187 rStrm >> maModel.maDefName;
189 static const sal_Int32 spnGrowShrinkTypes[] = { XML_insertClear, XML_insertDelete, XML_overwriteClear };
190 maModel.mnGrowShrinkType = STATIC_ARRAY_SELECT( spnGrowShrinkTypes, extractValue< sal_uInt8 >( nFlags, 6, 2 ), XML_insertDelete );
192 maModel.mbHeaders = getFlag( nFlags, BIFF12_QUERYTABLE_HEADERS );
193 maModel.mbRowNumbers = getFlag( nFlags, BIFF12_QUERYTABLE_ROWNUMBERS );
194 maModel.mbDisableRefresh = getFlag( nFlags, BIFF12_QUERYTABLE_DISABLEREFRESH );
195 maModel.mbBackground = getFlag( nFlags, BIFF12_QUERYTABLE_BACKGROUND );
196 maModel.mbFirstBackground = getFlag( nFlags, BIFF12_QUERYTABLE_FIRSTBACKGROUND );
197 maModel.mbRefreshOnLoad = getFlag( nFlags, BIFF12_QUERYTABLE_REFRESHONLOAD );
198 maModel.mbFillFormulas = getFlag( nFlags, BIFF12_QUERYTABLE_FILLFORMULAS );
199 maModel.mbRemoveDataOnSave = !getFlag( nFlags, BIFF12_QUERYTABLE_SAVEDATA ); // flag negated in BIFF12
200 maModel.mbDisableEdit = getFlag( nFlags, BIFF12_QUERYTABLE_DISABLEEDIT );
201 maModel.mbPreserveFormat = getFlag( nFlags, BIFF12_QUERYTABLE_PRESERVEFORMAT );
202 maModel.mbAdjustColWidth = getFlag( nFlags, BIFF12_QUERYTABLE_ADJUSTCOLWIDTH );
203 maModel.mbIntermediate = getFlag( nFlags, BIFF12_QUERYTABLE_INTERMEDIATE );
204 maModel.mbApplyNumFmt = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYNUMFMT );
205 maModel.mbApplyFont = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYFONT );
206 maModel.mbApplyAlignment = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYALIGNMENT );
207 maModel.mbApplyBorder = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYBORDER );
208 maModel.mbApplyFill = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYFILL );
209 maModel.mbApplyProtection = getFlag( nFlags, BIFF12_QUERYTABLE_APPLYPROTECTION );
212 void QueryTable::finalizeImport()
214 ConnectionRef xConnection = getConnections().getConnection( maModel.mnConnId );
215 OSL_ENSURE( xConnection.get(), "QueryTable::finalizeImport - missing connection object" );
216 if( xConnection.get() && (xConnection->getConnectionType() == BIFF12_CONNECTION_HTML) )
218 // check that valid web query properties exist
219 const WebPrModel* pWebPr = xConnection->getModel().mxWebPr.get();
220 if( pWebPr && !pWebPr->mbXml )
222 OUString aFileUrl = getBaseFilter().getAbsoluteUrl( pWebPr->maUrl );
223 if( !aFileUrl.isEmpty() )
225 // resolve destination cell range (stored as defined name containing the range)
226 OUString aDefName = maModel.maDefName.replace( ' ', '_' ).replace( '-', '_' );
227 DefinedNameRef xDefName = getDefinedNames().getByModelName( aDefName, getSheetIndex() );
228 OSL_ENSURE( xDefName.get(), "QueryTable::finalizeImport - missing defined name" );
229 if( xDefName.get() )
231 CellRangeAddress aDestRange;
232 bool bIsRange = xDefName->getAbsoluteRange( aDestRange ) && (aDestRange.Sheet == getSheetIndex());
233 OSL_ENSURE( bIsRange, "QueryTable::finalizeImport - defined name does not contain valid cell range" );
234 if( bIsRange && getAddressConverter().checkCellRange( aDestRange, false, true ) )
236 CellAddress aDestPos( aDestRange.Sheet, aDestRange.StartColumn, aDestRange.StartRow );
237 // find tables mode: entire document, all tables, or specific tables
238 OUString aTables = pWebPr->mbHtmlTables ? lclBuildWebQueryTables( pWebPr->maTables ) : "HTML_all";
239 if( !aTables.isEmpty() ) try
241 PropertySet aDocProps( getDocument() );
242 Reference< XAreaLinks > xAreaLinks( aDocProps.getAnyProperty( PROP_AreaLinks ), UNO_QUERY_THROW );
243 OUString aFilterName = "calc_HTML_WebQuery";
244 OUString aFilterOptions;
245 xAreaLinks->insertAtPosition( aDestPos, aFileUrl, aTables, aFilterName, aFilterOptions );
246 // set refresh interval (convert minutes to seconds)
247 sal_Int32 nRefreshPeriod = xConnection->getModel().mnInterval * 60;
248 if( nRefreshPeriod > 0 )
250 PropertySet aPropSet( lclFindAreaLink( xAreaLinks, aDestPos, aFileUrl, aTables, aFilterName, aFilterOptions ) );
251 aPropSet.setProperty( PROP_RefreshPeriod, nRefreshPeriod );
254 catch( Exception& )
264 QueryTableBuffer::QueryTableBuffer( const WorksheetHelper& rHelper ) :
265 WorksheetHelper( rHelper )
269 QueryTable& QueryTableBuffer::createQueryTable()
271 QueryTableVector::value_type xQueryTable( new QueryTable( *this ) );
272 maQueryTables.push_back( xQueryTable );
273 return *xQueryTable;
276 void QueryTableBuffer::finalizeImport()
278 maQueryTables.forEachMem( &QueryTable::finalizeImport );
281 } // namespace xls
282 } // namespace oox
284 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */