1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: scenariobuffer.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/scenariobuffer.hxx"
32 #include <com/sun/star/container/XIndexAccess.hpp>
33 #include <com/sun/star/sheet/XScenario.hpp>
34 #include <com/sun/star/sheet/XScenarios.hpp>
35 #include <com/sun/star/sheet/XScenariosSupplier.hpp>
36 #include <com/sun/star/sheet/XSpreadsheet.hpp>
37 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
38 #include "properties.hxx"
39 #include "oox/helper/attributelist.hxx"
40 #include "oox/helper/propertyset.hxx"
41 #include "oox/helper/recordinputstream.hxx"
42 #include "oox/xls/addressconverter.hxx"
43 #include "oox/xls/biffinputstream.hxx"
45 using ::rtl::OUString
;
46 using ::com::sun::star::uno::Exception
;
47 using ::com::sun::star::uno::Reference
;
48 using ::com::sun::star::uno::UNO_QUERY_THROW
;
49 using ::com::sun::star::uno::UNO_SET_THROW
;
50 using ::com::sun::star::container::XIndexAccess
;
51 using ::com::sun::star::container::XNameAccess
;
52 using ::com::sun::star::table::CellAddress
;
53 using ::com::sun::star::table::CellRangeAddress
;
54 using ::com::sun::star::table::XCell
;
55 using ::com::sun::star::sheet::XScenario
;
56 using ::com::sun::star::sheet::XScenarios
;
57 using ::com::sun::star::sheet::XScenariosSupplier
;
58 using ::com::sun::star::sheet::XSpreadsheet
;
63 // ============================================================================
67 const sal_Int32 BIFF_SCENARIO_DELETED
= 0x4000;
71 // ============================================================================
73 ScenarioCellModel::ScenarioCellModel() :
79 // ----------------------------------------------------------------------------
81 ScenarioModel::ScenarioModel() :
87 // ----------------------------------------------------------------------------
89 Scenario::Scenario( const WorkbookHelper
& rHelper
, sal_Int16 nSheet
) :
90 WorkbookHelper( rHelper
),
95 void Scenario::importScenario( const AttributeList
& rAttribs
)
97 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
98 maModel
.maComment
= rAttribs
.getXString( XML_comment
, OUString() );
99 maModel
.maUser
= rAttribs
.getXString( XML_user
, OUString() );
100 maModel
.mbLocked
= rAttribs
.getBool( XML_locked
, false );
101 maModel
.mbHidden
= rAttribs
.getBool( XML_hidden
, false );
104 void Scenario::importInputCells( const AttributeList
& rAttribs
)
106 ScenarioCellModel aModel
;
107 getAddressConverter().convertToCellAddressUnchecked( aModel
.maPos
, rAttribs
.getString( XML_r
, OUString() ), mnSheet
);
108 aModel
.maValue
= rAttribs
.getXString( XML_val
, OUString() );
109 aModel
.mnNumFmtId
= rAttribs
.getInteger( XML_numFmtId
, 0 );
110 aModel
.mbDeleted
= rAttribs
.getBool( XML_deleted
, false );
111 maCells
.push_back( aModel
);
114 void Scenario::importScenario( RecordInputStream
& rStrm
)
116 rStrm
.skip( 2 ); // cell count
117 // two longs instead of flag field
118 maModel
.mbLocked
= rStrm
.readInt32() != 0;
119 maModel
.mbHidden
= rStrm
.readInt32() != 0;
120 rStrm
>> maModel
.maName
>> maModel
.maComment
>> maModel
.maUser
;
123 void Scenario::importInputCells( RecordInputStream
& rStrm
)
125 // TODO: where is the deleted flag?
126 ScenarioCellModel aModel
;
130 aModel
.mnNumFmtId
= rStrm
.readuInt16();
131 rStrm
>> aModel
.maValue
;
132 getAddressConverter().convertToCellAddressUnchecked( aModel
.maPos
, aPos
, mnSheet
);
133 maCells
.push_back( aModel
);
136 void Scenario::importScenario( BiffInputStream
& rStrm
)
138 sal_uInt16 nCellCount
;
139 sal_uInt8 nNameLen
, nCommentLen
, nUserLen
;
141 // two bytes instead of flag field
142 maModel
.mbLocked
= rStrm
.readuInt8() != 0;
143 maModel
.mbHidden
= rStrm
.readuInt8() != 0;
144 rStrm
>> nNameLen
>> nCommentLen
>> nUserLen
;
145 maModel
.maName
= rStrm
.readUniStringBody( nNameLen
);
146 // user name: before comment (in difference to leading length field), repeated length
148 maModel
.maUser
= rStrm
.readUniString();
149 // comment: repeated length
150 if( nCommentLen
> 0 )
151 maModel
.maComment
= rStrm
.readUniString();
153 // list of cell addresses
154 for( sal_uInt16 nCell
= 0; !rStrm
.isEof() && (nCell
< nCellCount
); ++nCell
)
156 ScenarioCellModel aModel
;
159 // deleted flag is encoded in column index
160 aModel
.mbDeleted
= getFlag( aPos
.mnCol
, BIFF_SCENARIO_DELETED
);
161 setFlag( aPos
.mnCol
, BIFF_SCENARIO_DELETED
, false );
162 getAddressConverter().convertToCellAddressUnchecked( aModel
.maPos
, aPos
, mnSheet
);
163 maCells
.push_back( aModel
);
166 // list of cell values
167 for( ScenarioCellVector::iterator aIt
= maCells
.begin(), aEnd
= maCells
.end(); !rStrm
.isEof() && (aIt
!= aEnd
); ++aIt
)
168 aIt
->maValue
= rStrm
.readUniString();
171 void Scenario::finalizeImport()
173 AddressConverter
& rAddrConv
= getAddressConverter();
174 ::std::vector
< CellRangeAddress
> aRanges
;
175 for( ScenarioCellVector::iterator aIt
= maCells
.begin(), aEnd
= maCells
.end(); aIt
!= aEnd
; ++aIt
)
176 if( !aIt
->mbDeleted
&& rAddrConv
.checkCellAddress( aIt
->maPos
, true ) )
177 aRanges
.push_back( CellRangeAddress( aIt
->maPos
.Sheet
, aIt
->maPos
.Column
, aIt
->maPos
.Row
, aIt
->maPos
.Column
, aIt
->maPos
.Row
) );
179 if( !aRanges
.empty() && (maModel
.maName
.getLength() > 0) ) try
181 /* Find an unused name for the scenario (Calc stores scenario data in
182 hidden sheets named after the scenario following the base sheet). */
183 Reference
< XNameAccess
> xSheetsNA( getDocument()->getSheets(), UNO_QUERY_THROW
);
184 OUString aScenName
= ContainerHelper::getUnusedName( xSheetsNA
, maModel
.maName
, '_' );
186 // create the new scenario sheet
187 Reference
< XScenariosSupplier
> xScenariosSupp( getSheetFromDoc( mnSheet
), UNO_QUERY_THROW
);
188 Reference
< XScenarios
> xScenarios( xScenariosSupp
->getScenarios(), UNO_SET_THROW
);
189 xScenarios
->addNewByName( aScenName
, ContainerHelper::vectorToSequence( aRanges
), maModel
.maComment
);
191 // write scenario cell values
192 Reference
< XSpreadsheet
> xSheet( getSheetFromDoc( aScenName
), UNO_SET_THROW
);
193 for( ScenarioCellVector::iterator aIt
= maCells
.begin(), aEnd
= maCells
.end(); aIt
!= aEnd
; ++aIt
)
195 if( !aIt
->mbDeleted
) try
197 // use XCell::setFormula to auto-detect values and strings
198 Reference
< XCell
> xCell( xSheet
->getCellByPosition( aIt
->maPos
.Column
, aIt
->maPos
.Row
), UNO_SET_THROW
);
199 xCell
->setFormula( aIt
->maValue
);
206 // scenario properties
207 PropertySet
aPropSet( xScenarios
->getByName( aScenName
) );
208 aPropSet
.setProperty( PROP_IsActive
, false );
209 aPropSet
.setProperty( PROP_CopyBack
, false );
210 aPropSet
.setProperty( PROP_CopyStyles
, false );
211 aPropSet
.setProperty( PROP_CopyFormulas
, false );
212 aPropSet
.setProperty( PROP_Protected
, maModel
.mbLocked
);
213 // #112621# do not show/print scenario border
214 aPropSet
.setProperty( PROP_ShowBorder
, false );
215 aPropSet
.setProperty( PROP_PrintBorder
, false );
222 // ============================================================================
224 SheetScenariosModel::SheetScenariosModel() :
230 // ----------------------------------------------------------------------------
232 SheetScenarios::SheetScenarios( const WorkbookHelper
& rHelper
, sal_Int16 nSheet
) :
233 WorkbookHelper( rHelper
),
238 void SheetScenarios::importScenarios( const AttributeList
& rAttribs
)
240 maModel
.mnCurrent
= rAttribs
.getInteger( XML_current
, 0 );
241 maModel
.mnShown
= rAttribs
.getInteger( XML_show
, 0 );
244 void SheetScenarios::importScenarios( RecordInputStream
& rStrm
)
246 maModel
.mnCurrent
= rStrm
.readuInt16();
247 maModel
.mnShown
= rStrm
.readuInt16();
250 void SheetScenarios::importScenarios( BiffInputStream
& rStrm
)
252 rStrm
.skip( 2 ); // scenario count
253 maModel
.mnCurrent
= rStrm
.readuInt16();
254 maModel
.mnShown
= rStrm
.readuInt16();
256 // read following SCENARIO records
257 while( (rStrm
.getNextRecId() == BIFF_ID_SCENARIO
) && rStrm
.startNextRecord() )
258 createScenario().importScenario( rStrm
);
261 Scenario
& SheetScenarios::createScenario()
263 ScenarioVector::value_type
xScenario( new Scenario( *this, mnSheet
) );
264 maScenarios
.push_back( xScenario
);
268 void SheetScenarios::finalizeImport()
270 maScenarios
.forEachMem( &Scenario::finalizeImport
);
272 // activate a scenario
275 Reference
< XScenariosSupplier
> xScenariosSupp( getSheetFromDoc( mnSheet
), UNO_QUERY_THROW
);
276 Reference
< XIndexAccess
> xScenariosIA( xScenariosSupp
->getScenarios(), UNO_QUERY_THROW
);
277 Reference
< XScenario
> xScenario( xScenariosIA
->getByIndex( maModel
.mnShown
), UNO_QUERY_THROW
);
285 // ============================================================================
287 ScenarioBuffer::ScenarioBuffer( const WorkbookHelper
& rHelper
) :
288 WorkbookHelper( rHelper
)
292 SheetScenarios
& ScenarioBuffer::createSheetScenarios( sal_Int16 nSheet
)
294 SheetScenariosMap::mapped_type
& rxSheetScens
= maSheetScenarios
[ nSheet
];
296 rxSheetScens
.reset( new SheetScenarios( *this, nSheet
) );
297 return *rxSheetScens
;
300 void ScenarioBuffer::finalizeImport()
302 maSheetScenarios
.forEachMem( &SheetScenarios::finalizeImport
);
305 // ============================================================================