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