xref: /aoo42x/main/oox/source/xls/scenariobuffer.cxx (revision ca5ec200)
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