1*ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*ca5ec200SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*ca5ec200SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*ca5ec200SAndrew Rist * distributed with this work for additional information
6*ca5ec200SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*ca5ec200SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*ca5ec200SAndrew Rist * "License"); you may not use this file except in compliance
9*ca5ec200SAndrew Rist * with the License. You may obtain a copy of the License at
10*ca5ec200SAndrew Rist *
11*ca5ec200SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*ca5ec200SAndrew Rist *
13*ca5ec200SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*ca5ec200SAndrew Rist * software distributed under the License is distributed on an
15*ca5ec200SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ca5ec200SAndrew Rist * KIND, either express or implied. See the License for the
17*ca5ec200SAndrew Rist * specific language governing permissions and limitations
18*ca5ec200SAndrew Rist * under the License.
19*ca5ec200SAndrew Rist *
20*ca5ec200SAndrew Rist *************************************************************/
21*ca5ec200SAndrew Rist
22*ca5ec200SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #include "oox/xls/scenariobuffer.hxx"
25cdf0e10cSrcweir
26cdf0e10cSrcweir #include <com/sun/star/container/XIndexAccess.hpp>
27cdf0e10cSrcweir #include <com/sun/star/sheet/XScenario.hpp>
28cdf0e10cSrcweir #include <com/sun/star/sheet/XScenarios.hpp>
29cdf0e10cSrcweir #include <com/sun/star/sheet/XScenariosSupplier.hpp>
30cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheet.hpp>
31cdf0e10cSrcweir #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
32cdf0e10cSrcweir #include "oox/helper/attributelist.hxx"
33cdf0e10cSrcweir #include "oox/helper/containerhelper.hxx"
34cdf0e10cSrcweir #include "oox/helper/propertyset.hxx"
35cdf0e10cSrcweir #include "oox/xls/addressconverter.hxx"
36cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx"
37cdf0e10cSrcweir
38cdf0e10cSrcweir namespace oox {
39cdf0e10cSrcweir namespace xls {
40cdf0e10cSrcweir
41cdf0e10cSrcweir // ============================================================================
42cdf0e10cSrcweir
43cdf0e10cSrcweir using namespace ::com::sun::star::container;
44cdf0e10cSrcweir using namespace ::com::sun::star::sheet;
45cdf0e10cSrcweir using namespace ::com::sun::star::table;
46cdf0e10cSrcweir using namespace ::com::sun::star::uno;
47cdf0e10cSrcweir
48cdf0e10cSrcweir using ::rtl::OUString;
49cdf0e10cSrcweir
50cdf0e10cSrcweir // ============================================================================
51cdf0e10cSrcweir
52cdf0e10cSrcweir namespace {
53cdf0e10cSrcweir
54cdf0e10cSrcweir const sal_Int32 BIFF_SCENARIO_DELETED = 0x4000;
55cdf0e10cSrcweir
56cdf0e10cSrcweir } // namespace
57cdf0e10cSrcweir
58cdf0e10cSrcweir // ============================================================================
59cdf0e10cSrcweir
ScenarioCellModel()60cdf0e10cSrcweir ScenarioCellModel::ScenarioCellModel() :
61cdf0e10cSrcweir mnNumFmtId( 0 ),
62cdf0e10cSrcweir mbDeleted( false )
63cdf0e10cSrcweir {
64cdf0e10cSrcweir }
65cdf0e10cSrcweir
66cdf0e10cSrcweir // ----------------------------------------------------------------------------
67cdf0e10cSrcweir
ScenarioModel()68cdf0e10cSrcweir ScenarioModel::ScenarioModel() :
69cdf0e10cSrcweir mbLocked( false ),
70cdf0e10cSrcweir mbHidden( false )
71cdf0e10cSrcweir {
72cdf0e10cSrcweir }
73cdf0e10cSrcweir
74cdf0e10cSrcweir // ----------------------------------------------------------------------------
75cdf0e10cSrcweir
Scenario(const WorkbookHelper & rHelper,sal_Int16 nSheet)76cdf0e10cSrcweir Scenario::Scenario( const WorkbookHelper& rHelper, sal_Int16 nSheet ) :
77cdf0e10cSrcweir WorkbookHelper( rHelper ),
78cdf0e10cSrcweir mnSheet( nSheet )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir }
81cdf0e10cSrcweir
importScenario(const AttributeList & rAttribs)82cdf0e10cSrcweir void Scenario::importScenario( const AttributeList& rAttribs )
83cdf0e10cSrcweir {
84cdf0e10cSrcweir maModel.maName = rAttribs.getXString( XML_name, OUString() );
85cdf0e10cSrcweir maModel.maComment = rAttribs.getXString( XML_comment, OUString() );
86cdf0e10cSrcweir maModel.maUser = rAttribs.getXString( XML_user, OUString() );
87cdf0e10cSrcweir maModel.mbLocked = rAttribs.getBool( XML_locked, false );
88cdf0e10cSrcweir maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
89cdf0e10cSrcweir }
90cdf0e10cSrcweir
importInputCells(const AttributeList & rAttribs)91cdf0e10cSrcweir void Scenario::importInputCells( const AttributeList& rAttribs )
92cdf0e10cSrcweir {
93cdf0e10cSrcweir ScenarioCellModel aModel;
94cdf0e10cSrcweir getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, rAttribs.getString( XML_r, OUString() ), mnSheet );
95cdf0e10cSrcweir aModel.maValue = rAttribs.getXString( XML_val, OUString() );
96cdf0e10cSrcweir aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
97cdf0e10cSrcweir aModel.mbDeleted = rAttribs.getBool( XML_deleted, false );
98cdf0e10cSrcweir maCells.push_back( aModel );
99cdf0e10cSrcweir }
100cdf0e10cSrcweir
importScenario(SequenceInputStream & rStrm)101cdf0e10cSrcweir void Scenario::importScenario( SequenceInputStream& rStrm )
102cdf0e10cSrcweir {
103cdf0e10cSrcweir rStrm.skip( 2 ); // cell count
104cdf0e10cSrcweir // two longs instead of flag field
105cdf0e10cSrcweir maModel.mbLocked = rStrm.readInt32() != 0;
106cdf0e10cSrcweir maModel.mbHidden = rStrm.readInt32() != 0;
107cdf0e10cSrcweir rStrm >> maModel.maName >> maModel.maComment >> maModel.maUser;
108cdf0e10cSrcweir }
109cdf0e10cSrcweir
importInputCells(SequenceInputStream & rStrm)110cdf0e10cSrcweir void Scenario::importInputCells( SequenceInputStream& rStrm )
111cdf0e10cSrcweir {
112cdf0e10cSrcweir // TODO: where is the deleted flag?
113cdf0e10cSrcweir ScenarioCellModel aModel;
114cdf0e10cSrcweir BinAddress aPos;
115cdf0e10cSrcweir rStrm >> aPos;
116cdf0e10cSrcweir rStrm.skip( 8 );
117cdf0e10cSrcweir aModel.mnNumFmtId = rStrm.readuInt16();
118cdf0e10cSrcweir rStrm >> aModel.maValue;
119cdf0e10cSrcweir getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, aPos, mnSheet );
120cdf0e10cSrcweir maCells.push_back( aModel );
121cdf0e10cSrcweir }
122cdf0e10cSrcweir
importScenario(BiffInputStream & rStrm)123cdf0e10cSrcweir void Scenario::importScenario( BiffInputStream& rStrm )
124cdf0e10cSrcweir {
125cdf0e10cSrcweir sal_uInt16 nCellCount;
126cdf0e10cSrcweir sal_uInt8 nNameLen, nCommentLen, nUserLen;
127cdf0e10cSrcweir rStrm >> nCellCount;
128cdf0e10cSrcweir // two bytes instead of flag field
129cdf0e10cSrcweir maModel.mbLocked = rStrm.readuInt8() != 0;
130cdf0e10cSrcweir maModel.mbHidden = rStrm.readuInt8() != 0;
131cdf0e10cSrcweir rStrm >> nNameLen >> nCommentLen >> nUserLen;
132cdf0e10cSrcweir maModel.maName = rStrm.readUniStringBody( nNameLen );
133cdf0e10cSrcweir // user name: before comment (in difference to leading length field), repeated length
134cdf0e10cSrcweir if( nUserLen > 0 )
135cdf0e10cSrcweir maModel.maUser = rStrm.readUniString();
136cdf0e10cSrcweir // comment: repeated length
137cdf0e10cSrcweir if( nCommentLen > 0 )
138cdf0e10cSrcweir maModel.maComment = rStrm.readUniString();
139cdf0e10cSrcweir
140cdf0e10cSrcweir // list of cell addresses
141cdf0e10cSrcweir for( sal_uInt16 nCell = 0; !rStrm.isEof() && (nCell < nCellCount); ++nCell )
142cdf0e10cSrcweir {
143cdf0e10cSrcweir ScenarioCellModel aModel;
144cdf0e10cSrcweir BinAddress aPos;
145cdf0e10cSrcweir rStrm >> aPos;
146cdf0e10cSrcweir // deleted flag is encoded in column index
147cdf0e10cSrcweir aModel.mbDeleted = getFlag( aPos.mnCol, BIFF_SCENARIO_DELETED );
148cdf0e10cSrcweir setFlag( aPos.mnCol, BIFF_SCENARIO_DELETED, false );
149cdf0e10cSrcweir getAddressConverter().convertToCellAddressUnchecked( aModel.maPos, aPos, mnSheet );
150cdf0e10cSrcweir maCells.push_back( aModel );
151cdf0e10cSrcweir }
152cdf0e10cSrcweir
153cdf0e10cSrcweir // list of cell values
154cdf0e10cSrcweir for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); !rStrm.isEof() && (aIt != aEnd); ++aIt )
155cdf0e10cSrcweir aIt->maValue = rStrm.readUniString();
156cdf0e10cSrcweir }
157cdf0e10cSrcweir
finalizeImport()158cdf0e10cSrcweir void Scenario::finalizeImport()
159cdf0e10cSrcweir {
160cdf0e10cSrcweir AddressConverter& rAddrConv = getAddressConverter();
161cdf0e10cSrcweir ::std::vector< CellRangeAddress > aRanges;
162cdf0e10cSrcweir for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); aIt != aEnd; ++aIt )
163cdf0e10cSrcweir if( !aIt->mbDeleted && rAddrConv.checkCellAddress( aIt->maPos, true ) )
164cdf0e10cSrcweir aRanges.push_back( CellRangeAddress( aIt->maPos.Sheet, aIt->maPos.Column, aIt->maPos.Row, aIt->maPos.Column, aIt->maPos.Row ) );
165cdf0e10cSrcweir
166cdf0e10cSrcweir if( !aRanges.empty() && (maModel.maName.getLength() > 0) ) try
167cdf0e10cSrcweir {
168cdf0e10cSrcweir /* Find an unused name for the scenario (Calc stores scenario data in
169cdf0e10cSrcweir hidden sheets named after the scenario following the base sheet). */
170cdf0e10cSrcweir Reference< XNameAccess > xSheetsNA( getDocument()->getSheets(), UNO_QUERY_THROW );
171cdf0e10cSrcweir OUString aScenName = ContainerHelper::getUnusedName( xSheetsNA, maModel.maName, '_' );
172cdf0e10cSrcweir
173cdf0e10cSrcweir // create the new scenario sheet
174cdf0e10cSrcweir Reference< XScenariosSupplier > xScenariosSupp( getSheetFromDoc( mnSheet ), UNO_QUERY_THROW );
175cdf0e10cSrcweir Reference< XScenarios > xScenarios( xScenariosSupp->getScenarios(), UNO_SET_THROW );
176cdf0e10cSrcweir xScenarios->addNewByName( aScenName, ContainerHelper::vectorToSequence( aRanges ), maModel.maComment );
177cdf0e10cSrcweir
178cdf0e10cSrcweir // write scenario cell values
179cdf0e10cSrcweir Reference< XSpreadsheet > xSheet( getSheetFromDoc( aScenName ), UNO_SET_THROW );
180cdf0e10cSrcweir for( ScenarioCellVector::iterator aIt = maCells.begin(), aEnd = maCells.end(); aIt != aEnd; ++aIt )
181cdf0e10cSrcweir {
182cdf0e10cSrcweir if( !aIt->mbDeleted ) try
183cdf0e10cSrcweir {
184cdf0e10cSrcweir // use XCell::setFormula to auto-detect values and strings
185cdf0e10cSrcweir Reference< XCell > xCell( xSheet->getCellByPosition( aIt->maPos.Column, aIt->maPos.Row ), UNO_SET_THROW );
186cdf0e10cSrcweir xCell->setFormula( aIt->maValue );
187cdf0e10cSrcweir }
188cdf0e10cSrcweir catch( Exception& )
189cdf0e10cSrcweir {
190cdf0e10cSrcweir }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir
193cdf0e10cSrcweir // scenario properties
194cdf0e10cSrcweir PropertySet aPropSet( xScenarios->getByName( aScenName ) );
195cdf0e10cSrcweir aPropSet.setProperty( PROP_IsActive, false );
196cdf0e10cSrcweir aPropSet.setProperty( PROP_CopyBack, false );
197cdf0e10cSrcweir aPropSet.setProperty( PROP_CopyStyles, false );
198cdf0e10cSrcweir aPropSet.setProperty( PROP_CopyFormulas, false );
199cdf0e10cSrcweir aPropSet.setProperty( PROP_Protected, maModel.mbLocked );
200cdf0e10cSrcweir // #112621# do not show/print scenario border
201cdf0e10cSrcweir aPropSet.setProperty( PROP_ShowBorder, false );
202cdf0e10cSrcweir aPropSet.setProperty( PROP_PrintBorder, false );
203cdf0e10cSrcweir }
204cdf0e10cSrcweir catch( Exception& )
205cdf0e10cSrcweir {
206cdf0e10cSrcweir }
207cdf0e10cSrcweir }
208cdf0e10cSrcweir
209cdf0e10cSrcweir // ============================================================================
210cdf0e10cSrcweir
SheetScenariosModel()211cdf0e10cSrcweir SheetScenariosModel::SheetScenariosModel() :
212cdf0e10cSrcweir mnCurrent( 0 ),
213cdf0e10cSrcweir mnShown( 0 )
214cdf0e10cSrcweir {
215cdf0e10cSrcweir }
216cdf0e10cSrcweir
217cdf0e10cSrcweir // ----------------------------------------------------------------------------
218cdf0e10cSrcweir
SheetScenarios(const WorkbookHelper & rHelper,sal_Int16 nSheet)219cdf0e10cSrcweir SheetScenarios::SheetScenarios( const WorkbookHelper& rHelper, sal_Int16 nSheet ) :
220cdf0e10cSrcweir WorkbookHelper( rHelper ),
221cdf0e10cSrcweir mnSheet( nSheet )
222cdf0e10cSrcweir {
223cdf0e10cSrcweir }
224cdf0e10cSrcweir
importScenarios(const AttributeList & rAttribs)225cdf0e10cSrcweir void SheetScenarios::importScenarios( const AttributeList& rAttribs )
226cdf0e10cSrcweir {
227cdf0e10cSrcweir maModel.mnCurrent = rAttribs.getInteger( XML_current, 0 );
228cdf0e10cSrcweir maModel.mnShown = rAttribs.getInteger( XML_show, 0 );
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
importScenarios(SequenceInputStream & rStrm)231cdf0e10cSrcweir void SheetScenarios::importScenarios( SequenceInputStream& rStrm )
232cdf0e10cSrcweir {
233cdf0e10cSrcweir maModel.mnCurrent = rStrm.readuInt16();
234cdf0e10cSrcweir maModel.mnShown = rStrm.readuInt16();
235cdf0e10cSrcweir }
236cdf0e10cSrcweir
importScenarios(BiffInputStream & rStrm)237cdf0e10cSrcweir void SheetScenarios::importScenarios( BiffInputStream& rStrm )
238cdf0e10cSrcweir {
239cdf0e10cSrcweir rStrm.skip( 2 ); // scenario count
240cdf0e10cSrcweir maModel.mnCurrent = rStrm.readuInt16();
241cdf0e10cSrcweir maModel.mnShown = rStrm.readuInt16();
242cdf0e10cSrcweir
243cdf0e10cSrcweir // read following SCENARIO records
244cdf0e10cSrcweir while( (rStrm.getNextRecId() == BIFF_ID_SCENARIO) && rStrm.startNextRecord() )
245cdf0e10cSrcweir createScenario().importScenario( rStrm );
246cdf0e10cSrcweir }
247cdf0e10cSrcweir
createScenario()248cdf0e10cSrcweir Scenario& SheetScenarios::createScenario()
249cdf0e10cSrcweir {
250cdf0e10cSrcweir ScenarioVector::value_type xScenario( new Scenario( *this, mnSheet ) );
251cdf0e10cSrcweir maScenarios.push_back( xScenario );
252cdf0e10cSrcweir return *xScenario;
253cdf0e10cSrcweir }
254cdf0e10cSrcweir
finalizeImport()255cdf0e10cSrcweir void SheetScenarios::finalizeImport()
256cdf0e10cSrcweir {
257cdf0e10cSrcweir maScenarios.forEachMem( &Scenario::finalizeImport );
258cdf0e10cSrcweir
259cdf0e10cSrcweir // activate a scenario
260cdf0e10cSrcweir try
261cdf0e10cSrcweir {
262cdf0e10cSrcweir Reference< XScenariosSupplier > xScenariosSupp( getSheetFromDoc( mnSheet ), UNO_QUERY_THROW );
263cdf0e10cSrcweir Reference< XIndexAccess > xScenariosIA( xScenariosSupp->getScenarios(), UNO_QUERY_THROW );
264cdf0e10cSrcweir Reference< XScenario > xScenario( xScenariosIA->getByIndex( maModel.mnShown ), UNO_QUERY_THROW );
265cdf0e10cSrcweir xScenario->apply();
266cdf0e10cSrcweir }
267cdf0e10cSrcweir catch( Exception& )
268cdf0e10cSrcweir {
269cdf0e10cSrcweir }
270cdf0e10cSrcweir }
271cdf0e10cSrcweir
272cdf0e10cSrcweir // ============================================================================
273cdf0e10cSrcweir
ScenarioBuffer(const WorkbookHelper & rHelper)274cdf0e10cSrcweir ScenarioBuffer::ScenarioBuffer( const WorkbookHelper& rHelper ) :
275cdf0e10cSrcweir WorkbookHelper( rHelper )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir }
278cdf0e10cSrcweir
createSheetScenarios(sal_Int16 nSheet)279cdf0e10cSrcweir SheetScenarios& ScenarioBuffer::createSheetScenarios( sal_Int16 nSheet )
280cdf0e10cSrcweir {
281cdf0e10cSrcweir SheetScenariosMap::mapped_type& rxSheetScens = maSheetScenarios[ nSheet ];
282cdf0e10cSrcweir if( !rxSheetScens )
283cdf0e10cSrcweir rxSheetScens.reset( new SheetScenarios( *this, nSheet ) );
284cdf0e10cSrcweir return *rxSheetScens;
285cdf0e10cSrcweir }
286cdf0e10cSrcweir
finalizeImport()287cdf0e10cSrcweir void ScenarioBuffer::finalizeImport()
288cdf0e10cSrcweir {
289cdf0e10cSrcweir maSheetScenarios.forEachMem( &SheetScenarios::finalizeImport );
290cdf0e10cSrcweir }
291cdf0e10cSrcweir
292cdf0e10cSrcweir // ============================================================================
293cdf0e10cSrcweir
294cdf0e10cSrcweir } // namespace xls
295cdf0e10cSrcweir } // namespace oox
296