1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/xls/workbooksettings.hxx" 25 26 #include <com/sun/star/sheet/XCalculatable.hpp> 27 #include <com/sun/star/util/Date.hpp> 28 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 29 #include <comphelper/mediadescriptor.hxx> 30 #include "oox/core/filterbase.hxx" 31 #include "oox/helper/attributelist.hxx" 32 #include "oox/helper/propertyset.hxx" 33 #include "oox/xls/biffinputstream.hxx" 34 #include "oox/xls/unitconverter.hxx" 35 36 namespace oox { 37 namespace xls { 38 39 // ============================================================================ 40 41 using namespace ::com::sun::star::beans; 42 using namespace ::com::sun::star::sheet; 43 using namespace ::com::sun::star::uno; 44 using namespace ::com::sun::star::util; 45 46 using ::comphelper::MediaDescriptor; 47 using ::oox::core::CodecHelper; 48 using ::rtl::OUString; 49 50 // ============================================================================ 51 52 namespace { 53 54 const sal_uInt32 BIFF12_WORKBOOKPR_DATE1904 = 0x00000001; 55 const sal_uInt32 BIFF12_WORKBOOKPR_STRIPEXT = 0x00000080; 56 57 const sal_uInt16 BIFF12_CALCPR_A1 = 0x0002; 58 const sal_uInt16 BIFF12_CALCPR_ITERATE = 0x0004; 59 const sal_uInt16 BIFF12_CALCPR_FULLPRECISION = 0x0008; 60 const sal_uInt16 BIFF12_CALCPR_CALCCOMPLETED = 0x0010; 61 const sal_uInt16 BIFF12_CALCPR_CALCONSAVE = 0x0020; 62 const sal_uInt16 BIFF12_CALCPR_CONCURRENT = 0x0040; 63 const sal_uInt16 BIFF12_CALCPR_MANUALPROC = 0x0080; 64 65 // no predefined constants for show objects mode 66 const sal_Int16 API_SHOWMODE_SHOW = 0; /// Show drawing objects. 67 const sal_Int16 API_SHOWMODE_HIDE = 1; /// Hide drawing objects. 68 const sal_Int16 API_SHOWMODE_PLACEHOLDER = 2; /// Show placeholders for drawing objects. 69 70 } // namespace 71 72 // ============================================================================ 73 74 FileSharingModel::FileSharingModel() : 75 mnPasswordHash( 0 ), 76 mbRecommendReadOnly( false ) 77 { 78 } 79 80 // ============================================================================ 81 82 WorkbookSettingsModel::WorkbookSettingsModel() : 83 mnShowObjectMode( XML_all ), 84 mnUpdateLinksMode( XML_userSet ), 85 mnDefaultThemeVer( -1 ), 86 mbDateMode1904( false ), 87 mbSaveExtLinkValues( true ) 88 { 89 } 90 91 void WorkbookSettingsModel::setBiffObjectMode( sal_uInt16 nObjMode ) 92 { 93 static const sal_Int32 spnObjModes[] = { XML_all, XML_placeholders, XML_none }; 94 mnShowObjectMode = STATIC_ARRAY_SELECT( spnObjModes, nObjMode, XML_all ); 95 } 96 97 // ============================================================================ 98 99 CalcSettingsModel::CalcSettingsModel() : 100 mfIterateDelta( 0.001 ), 101 mnCalcId( -1 ), 102 mnRefMode( XML_A1 ), 103 mnCalcMode( XML_auto ), 104 mnIterateCount( 100 ), 105 mnProcCount( -1 ), 106 mbCalcOnSave( true ), 107 mbCalcCompleted( true ), 108 mbFullPrecision( true ), 109 mbIterate( false ), 110 mbConcurrent( true ), 111 mbUseNlr( false ) 112 { 113 } 114 115 // ============================================================================ 116 117 WorkbookSettings::WorkbookSettings( const WorkbookHelper& rHelper ) : 118 WorkbookHelper( rHelper ) 119 { 120 } 121 122 void WorkbookSettings::importFileSharing( const AttributeList& rAttribs ) 123 { 124 maFileSharing.maUserName = rAttribs.getXString( XML_userName, OUString() ); 125 maFileSharing.mnPasswordHash = CodecHelper::getPasswordHash( rAttribs, XML_reservationPassword ); 126 maFileSharing.mbRecommendReadOnly = rAttribs.getBool( XML_readOnlyRecommended, false ); 127 } 128 129 void WorkbookSettings::importWorkbookPr( const AttributeList& rAttribs ) 130 { 131 maBookSettings.maCodeName = rAttribs.getString( XML_codeName, OUString() ); 132 maBookSettings.mnShowObjectMode = rAttribs.getToken( XML_showObjects, XML_all ); 133 maBookSettings.mnUpdateLinksMode = rAttribs.getToken( XML_updateLinks, XML_userSet ); 134 maBookSettings.mnDefaultThemeVer = rAttribs.getInteger( XML_defaultThemeVersion, -1 ); 135 maBookSettings.mbSaveExtLinkValues = rAttribs.getBool( XML_saveExternalLinkValues, true ); 136 setDateMode( rAttribs.getBool( XML_date1904, false ) ); 137 } 138 139 void WorkbookSettings::importCalcPr( const AttributeList& rAttribs ) 140 { 141 maCalcSettings.mfIterateDelta = rAttribs.getDouble( XML_iterateDelta, 0.0001 ); 142 maCalcSettings.mnCalcId = rAttribs.getInteger( XML_calcId, -1 ); 143 maCalcSettings.mnRefMode = rAttribs.getToken( XML_refMode, XML_A1 ); 144 maCalcSettings.mnCalcMode = rAttribs.getToken( XML_calcMode, XML_auto ); 145 maCalcSettings.mnIterateCount = rAttribs.getInteger( XML_iterateCount, 100 ); 146 maCalcSettings.mnProcCount = rAttribs.getInteger( XML_concurrentManualCount, -1 ); 147 maCalcSettings.mbCalcOnSave = rAttribs.getBool( XML_calcOnSave, true ); 148 maCalcSettings.mbCalcCompleted = rAttribs.getBool( XML_calcCompleted, true ); 149 maCalcSettings.mbFullPrecision = rAttribs.getBool( XML_fullPrecision, true ); 150 maCalcSettings.mbIterate = rAttribs.getBool( XML_iterate, false ); 151 maCalcSettings.mbConcurrent = rAttribs.getBool( XML_concurrentCalc, true ); 152 } 153 154 void WorkbookSettings::importFileSharing( SequenceInputStream& rStrm ) 155 { 156 maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0; 157 rStrm >> maFileSharing.mnPasswordHash >> maFileSharing.maUserName; 158 } 159 160 void WorkbookSettings::importWorkbookPr( SequenceInputStream& rStrm ) 161 { 162 sal_uInt32 nFlags; 163 rStrm >> nFlags >> maBookSettings.mnDefaultThemeVer >> maBookSettings.maCodeName; 164 maBookSettings.setBiffObjectMode( extractValue< sal_uInt16 >( nFlags, 13, 2 ) ); 165 // set flag means: strip external link values 166 maBookSettings.mbSaveExtLinkValues = !getFlag( nFlags, BIFF12_WORKBOOKPR_STRIPEXT ); 167 setDateMode( getFlag( nFlags, BIFF12_WORKBOOKPR_DATE1904 ) ); 168 } 169 170 void WorkbookSettings::importCalcPr( SequenceInputStream& rStrm ) 171 { 172 sal_Int32 nCalcMode, nProcCount; 173 sal_uInt16 nFlags; 174 rStrm >> maCalcSettings.mnCalcId >> nCalcMode >> maCalcSettings.mnIterateCount >> maCalcSettings.mfIterateDelta >> nProcCount >> nFlags; 175 176 static const sal_Int32 spnCalcModes[] = { XML_manual, XML_auto, XML_autoNoTable }; 177 maCalcSettings.mnRefMode = getFlagValue( nFlags, BIFF12_CALCPR_A1, XML_A1, XML_R1C1 ); 178 maCalcSettings.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); 179 maCalcSettings.mnProcCount = getFlagValue< sal_Int32 >( nFlags, BIFF12_CALCPR_MANUALPROC, nProcCount, -1 ); 180 maCalcSettings.mbCalcOnSave = getFlag( nFlags, BIFF12_CALCPR_CALCONSAVE ); 181 maCalcSettings.mbCalcCompleted = getFlag( nFlags, BIFF12_CALCPR_CALCCOMPLETED ); 182 maCalcSettings.mbFullPrecision = getFlag( nFlags, BIFF12_CALCPR_FULLPRECISION ); 183 maCalcSettings.mbIterate = getFlag( nFlags, BIFF12_CALCPR_ITERATE ); 184 maCalcSettings.mbConcurrent = getFlag( nFlags, BIFF12_CALCPR_CONCURRENT ); 185 } 186 187 void WorkbookSettings::setSaveExtLinkValues( bool bSaveExtLinks ) 188 { 189 maBookSettings.mbSaveExtLinkValues = bSaveExtLinks; 190 } 191 192 void WorkbookSettings::importBookBool( BiffInputStream& rStrm ) 193 { 194 // value of 0 means save external values, value of 1 means strip external values 195 maBookSettings.mbSaveExtLinkValues = rStrm.readuInt16() == 0; 196 } 197 198 void WorkbookSettings::importCalcCount( BiffInputStream& rStrm ) 199 { 200 maCalcSettings.mnIterateCount = rStrm.readuInt16(); 201 } 202 203 void WorkbookSettings::importCalcMode( BiffInputStream& rStrm ) 204 { 205 sal_Int16 nCalcMode = rStrm.readInt16() + 1; 206 static const sal_Int32 spnCalcModes[] = { XML_autoNoTable, XML_manual, XML_auto }; 207 maCalcSettings.mnCalcMode = STATIC_ARRAY_SELECT( spnCalcModes, nCalcMode, XML_auto ); 208 } 209 210 void WorkbookSettings::importCodeName( BiffInputStream& rStrm ) 211 { 212 maBookSettings.maCodeName = rStrm.readUniString(); 213 } 214 215 void WorkbookSettings::importDateMode( BiffInputStream& rStrm ) 216 { 217 setDateMode( rStrm.readuInt16() != 0 ); 218 } 219 220 void WorkbookSettings::importDelta( BiffInputStream& rStrm ) 221 { 222 rStrm >> maCalcSettings.mfIterateDelta; 223 } 224 225 void WorkbookSettings::importFileSharing( BiffInputStream& rStrm ) 226 { 227 maFileSharing.mbRecommendReadOnly = rStrm.readuInt16() != 0; 228 rStrm >> maFileSharing.mnPasswordHash; 229 if( getBiff() == BIFF8 ) 230 { 231 sal_uInt16 nStrLen = rStrm.readuInt16(); 232 // there is no string flags field if string is empty 233 if( nStrLen > 0 ) 234 maFileSharing.maUserName = rStrm.readUniStringBody( nStrLen ); 235 } 236 else 237 { 238 maFileSharing.maUserName = rStrm.readByteStringUC( false, getTextEncoding() ); 239 } 240 } 241 242 void WorkbookSettings::importHideObj( BiffInputStream& rStrm ) 243 { 244 maBookSettings.setBiffObjectMode( rStrm.readuInt16() ); 245 } 246 247 void WorkbookSettings::importIteration( BiffInputStream& rStrm ) 248 { 249 maCalcSettings.mbIterate = rStrm.readuInt16() != 0; 250 } 251 252 void WorkbookSettings::importPrecision( BiffInputStream& rStrm ) 253 { 254 maCalcSettings.mbFullPrecision = rStrm.readuInt16() != 0; 255 } 256 257 void WorkbookSettings::importRefMode( BiffInputStream& rStrm ) 258 { 259 maCalcSettings.mnRefMode = (rStrm.readuInt16() == 0) ? XML_R1C1 : XML_A1; 260 } 261 262 void WorkbookSettings::importSaveRecalc( BiffInputStream& rStrm ) 263 { 264 maCalcSettings.mbCalcOnSave = rStrm.readuInt16() != 0; 265 } 266 267 void WorkbookSettings::importUncalced( BiffInputStream& ) 268 { 269 // existence of this record indicates incomplete recalc 270 maCalcSettings.mbCalcCompleted = false; 271 } 272 273 void WorkbookSettings::importUsesElfs( BiffInputStream& rStrm ) 274 { 275 maCalcSettings.mbUseNlr = rStrm.readuInt16() != 0; 276 } 277 278 void WorkbookSettings::finalizeImport() 279 { 280 // default settings 281 PropertySet aPropSet( getDocument() ); 282 switch( getFilterType() ) 283 { 284 case FILTER_OOXML: 285 case FILTER_BIFF: 286 aPropSet.setProperty( PROP_IgnoreCase, true ); // always in Excel 287 aPropSet.setProperty( PROP_RegularExpressions, false ); // not supported in Excel 288 break; 289 case FILTER_UNKNOWN: 290 break; 291 } 292 293 // write protection 294 if( maFileSharing.mbRecommendReadOnly || (maFileSharing.mnPasswordHash != 0) ) try 295 { 296 getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "ReadOnly" ) ] <<= true; 297 298 Reference< XPropertySet > xDocumentSettings( getBaseFilter().getModelFactory()->createInstance( 299 CREATE_OUSTRING( "com.sun.star.document.Settings" ) ), UNO_QUERY_THROW ); 300 PropertySet aSettingsProp( xDocumentSettings ); 301 if( maFileSharing.mbRecommendReadOnly ) 302 aSettingsProp.setProperty( PROP_LoadReadonly, true ); 303 // if( maFileSharing.mnPasswordHash != 0 ) 304 // aSettingsProp.setProperty( PROP_ModifyPasswordHash, static_cast< sal_Int32 >( maFileSharing.mnPasswordHash ) ); 305 } 306 catch( Exception& ) 307 { 308 } 309 310 // calculation settings 311 Date aNullDate = getNullDate(); 312 313 aPropSet.setProperty( PROP_NullDate, aNullDate ); 314 aPropSet.setProperty( PROP_IsIterationEnabled, maCalcSettings.mbIterate ); 315 aPropSet.setProperty( PROP_IterationCount, maCalcSettings.mnIterateCount ); 316 aPropSet.setProperty( PROP_IterationEpsilon, maCalcSettings.mfIterateDelta ); 317 aPropSet.setProperty( PROP_CalcAsShown, !maCalcSettings.mbFullPrecision ); 318 aPropSet.setProperty( PROP_LookUpLabels, maCalcSettings.mbUseNlr ); 319 320 Reference< XNumberFormatsSupplier > xNumFmtsSupp( getDocument(), UNO_QUERY ); 321 if( xNumFmtsSupp.is() ) 322 { 323 PropertySet aNumFmtProp( xNumFmtsSupp->getNumberFormatSettings() ); 324 aNumFmtProp.setProperty( PROP_NullDate, aNullDate ); 325 } 326 327 Reference< XCalculatable > xCalculatable( getDocument(), UNO_QUERY ); 328 if( xCalculatable.is() ) 329 xCalculatable->enableAutomaticCalculation( (maCalcSettings.mnCalcMode == XML_auto) || (maCalcSettings.mnCalcMode == XML_autoNoTable) ); 330 331 // VBA code name 332 aPropSet.setProperty( PROP_CodeName, maBookSettings.maCodeName ); 333 } 334 335 sal_Int16 WorkbookSettings::getApiShowObjectMode() const 336 { 337 switch( maBookSettings.mnShowObjectMode ) 338 { 339 case XML_all: return API_SHOWMODE_SHOW; 340 case XML_none: return API_SHOWMODE_HIDE; 341 // #i80528# placeholders not supported anymore, but this is handled internally in Calc 342 case XML_placeholders: return API_SHOWMODE_PLACEHOLDER; 343 } 344 return API_SHOWMODE_SHOW; 345 } 346 347 Date WorkbookSettings::getNullDate() const 348 { 349 static const Date saDate1900( 30, 12, 1899 ), saDate1904( 1, 1, 1904 ); 350 return maBookSettings.mbDateMode1904 ? saDate1904 : saDate1900; 351 } 352 353 void WorkbookSettings::setDateMode( bool bDateMode1904 ) 354 { 355 maBookSettings.mbDateMode1904 = bDateMode1904; 356 getUnitConverter().finalizeNullDate( getNullDate() ); 357 } 358 359 // ============================================================================ 360 361 } // namespace xls 362 } // namespace oox 363