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/viewsettings.hxx" 25 26 #include <com/sun/star/awt/Point.hpp> 27 #include <com/sun/star/awt/Size.hpp> 28 #include <com/sun/star/beans/PropertyValue.hpp> 29 #include <com/sun/star/container/XIndexContainer.hpp> 30 #include <com/sun/star/container/XNameContainer.hpp> 31 #include <com/sun/star/document/XViewDataSupplier.hpp> 32 #include <comphelper/mediadescriptor.hxx> 33 #include "oox/core/filterbase.hxx" 34 #include "oox/helper/attributelist.hxx" 35 #include "oox/helper/containerhelper.hxx" 36 #include "oox/helper/propertymap.hxx" 37 #include "oox/helper/propertyset.hxx" 38 #include "oox/xls/addressconverter.hxx" 39 #include "oox/xls/biffinputstream.hxx" 40 #include "oox/xls/unitconverter.hxx" 41 #include "oox/xls/workbooksettings.hxx" 42 #include "oox/xls/worksheetbuffer.hxx" 43 44 namespace oox { 45 namespace xls { 46 47 // ============================================================================ 48 49 using namespace ::com::sun::star::awt; 50 using namespace ::com::sun::star::container; 51 using namespace ::com::sun::star::document; 52 using namespace ::com::sun::star::table; 53 using namespace ::com::sun::star::uno; 54 55 using ::oox::core::FilterBase; 56 using ::rtl::OUString; 57 58 // ============================================================================ 59 60 namespace { 61 62 const sal_Int32 OOX_BOOKVIEW_TABBARRATIO_DEF = 600; /// Default tabbar ratio. 63 const sal_Int32 OOX_SHEETVIEW_NORMALZOOM_DEF = 100; /// Default zoom for normal view. 64 const sal_Int32 OOX_SHEETVIEW_SHEETLAYZOOM_DEF = 60; /// Default zoom for pagebreak preview. 65 const sal_Int32 OOX_SHEETVIEW_PAGELAYZOOM_DEF = 100; /// Default zoom for page layout view. 66 67 const sal_uInt8 BIFF12_PANE_FROZEN = 0x01; 68 const sal_uInt8 BIFF12_PANE_FROZENNOSPLIT = 0x02; 69 70 const sal_uInt16 BIFF12_SHEETVIEW_WINPROTECTED = 0x0001; 71 const sal_uInt16 BIFF12_SHEETVIEW_SHOWFORMULAS = 0x0002; 72 const sal_uInt16 BIFF12_SHEETVIEW_SHOWGRID = 0x0004; 73 const sal_uInt16 BIFF12_SHEETVIEW_SHOWHEADINGS = 0x0008; 74 const sal_uInt16 BIFF12_SHEETVIEW_SHOWZEROS = 0x0010; 75 const sal_uInt16 BIFF12_SHEETVIEW_RIGHTTOLEFT = 0x0020; 76 const sal_uInt16 BIFF12_SHEETVIEW_SELECTED = 0x0040; 77 const sal_uInt16 BIFF12_SHEETVIEW_SHOWRULER = 0x0080; 78 const sal_uInt16 BIFF12_SHEETVIEW_SHOWOUTLINE = 0x0100; 79 const sal_uInt16 BIFF12_SHEETVIEW_DEFGRIDCOLOR = 0x0200; 80 const sal_uInt16 BIFF12_SHEETVIEW_SHOWWHITESPACE = 0x0400; 81 82 const sal_uInt16 BIFF12_CHARTSHEETVIEW_SELECTED = 0x0001; 83 const sal_uInt16 BIFF12_CHARTSHEETVIEW_ZOOMTOFIT = 0x0002; 84 85 const sal_uInt8 BIFF12_WBVIEW_HIDDEN = 0x01; 86 const sal_uInt8 BIFF12_WBVIEW_MINIMIZED = 0x02; 87 const sal_uInt8 BIFF12_WBVIEW_SHOWHORSCROLL = 0x08; 88 const sal_uInt8 BIFF12_WBVIEW_SHOWVERSCROLL = 0x10; 89 const sal_uInt8 BIFF12_WBVIEW_SHOWTABBAR = 0x20; 90 const sal_uInt8 BIFF12_WBVIEW_AUTOFILTERGROUP = 0x40; 91 92 const sal_uInt8 BIFF_PANE_BOTTOMRIGHT = 0; /// Bottom-right pane. 93 const sal_uInt8 BIFF_PANE_TOPRIGHT = 1; /// Right, or top-right pane. 94 const sal_uInt8 BIFF_PANE_BOTTOMLEFT = 2; /// Bottom, or bottom-left pane. 95 const sal_uInt8 BIFF_PANE_TOPLEFT = 3; /// Single, top, left, or top-left pane. 96 97 const sal_uInt16 BIFF_WINDOW1_HIDDEN = 0x0001; 98 const sal_uInt16 BIFF_WINDOW1_MINIMIZED = 0x0002; 99 const sal_uInt16 BIFF_WINDOW1_SHOWHORSCROLL = 0x0008; 100 const sal_uInt16 BIFF_WINDOW1_SHOWVERSCROLL = 0x0010; 101 const sal_uInt16 BIFF_WINDOW1_SHOWTABBAR = 0x0020; 102 103 const sal_uInt16 BIFF_WINDOW2_SHOWFORMULAS = 0x0001; 104 const sal_uInt16 BIFF_WINDOW2_SHOWGRID = 0x0002; 105 const sal_uInt16 BIFF_WINDOW2_SHOWHEADINGS = 0x0004; 106 const sal_uInt16 BIFF_WINDOW2_FROZEN = 0x0008; 107 const sal_uInt16 BIFF_WINDOW2_SHOWZEROS = 0x0010; 108 const sal_uInt16 BIFF_WINDOW2_DEFGRIDCOLOR = 0x0020; 109 const sal_uInt16 BIFF_WINDOW2_RIGHTTOLEFT = 0x0040; 110 const sal_uInt16 BIFF_WINDOW2_SHOWOUTLINE = 0x0080; 111 const sal_uInt16 BIFF_WINDOW2_FROZENNOSPLIT = 0x0100; 112 const sal_uInt16 BIFF_WINDOW2_SELECTED = 0x0200; 113 const sal_uInt16 BIFF_WINDOW2_DISPLAYED = 0x0400; 114 const sal_uInt16 BIFF_WINDOW2_PAGEBREAKMODE = 0x0800; 115 116 // Attention: view settings in Calc do not use com.sun.star.view.DocumentZoomType! 117 const sal_Int16 API_ZOOMTYPE_PERCENT = 0; /// Zoom value in percent. 118 119 const sal_Int32 API_ZOOMVALUE_MIN = 20; /// Minimum zoom in Calc. 120 const sal_Int32 API_ZOOMVALUE_MAX = 400; /// Maximum zoom in Calc. 121 122 // no predefined constants for split mode 123 const sal_Int16 API_SPLITMODE_NONE = 0; /// No splits in window. 124 const sal_Int16 API_SPLITMODE_SPLIT = 1; /// Window is split. 125 const sal_Int16 API_SPLITMODE_FREEZE = 2; /// Window has frozen panes. 126 127 // no predefined constants for pane idetifiers 128 const sal_Int16 API_SPLITPANE_TOPLEFT = 0; /// Top-left, or top pane. 129 const sal_Int16 API_SPLITPANE_TOPRIGHT = 1; /// Top-right pane. 130 const sal_Int16 API_SPLITPANE_BOTTOMLEFT = 2; /// Bottom-left, bottom, left, or single pane. 131 const sal_Int16 API_SPLITPANE_BOTTOMRIGHT = 3; /// Bottom-right, or right pane. 132 133 // ---------------------------------------------------------------------------- 134 135 /** Returns the OOXML pane identifier from the passed BIFF pane id. */ 136 sal_Int32 lclGetOoxPaneId( sal_Int32 nBiffPaneId, sal_Int32 nDefaultPaneId ) 137 { 138 static const sal_Int32 spnPaneIds[] = { XML_bottomRight, XML_topRight, XML_bottomLeft, XML_topLeft }; 139 return STATIC_ARRAY_SELECT( spnPaneIds, nBiffPaneId, nDefaultPaneId ); 140 } 141 142 } // namespace 143 144 // ============================================================================ 145 146 PaneSelectionModel::PaneSelectionModel() : 147 mnActiveCellId( 0 ) 148 { 149 } 150 151 // ---------------------------------------------------------------------------- 152 153 SheetViewModel::SheetViewModel() : 154 mnWorkbookViewId( 0 ), 155 mnViewType( XML_normal ), 156 mnActivePaneId( XML_topLeft ), 157 mnPaneState( XML_split ), 158 mfSplitX( 0.0 ), 159 mfSplitY( 0.0 ), 160 mnCurrentZoom( 0 ), 161 mnNormalZoom( 0 ), 162 mnSheetLayoutZoom( 0 ), 163 mnPageLayoutZoom( 0 ), 164 mbSelected( false ), 165 mbRightToLeft( false ), 166 mbDefGridColor( true ), 167 mbShowFormulas( false ), 168 mbShowGrid( true ), 169 mbShowHeadings( true ), 170 mbShowZeros( true ), 171 mbShowOutline( true ), 172 mbZoomToFit( false ) 173 { 174 maGridColor.setIndexed( OOX_COLOR_WINDOWTEXT ); 175 } 176 177 bool SheetViewModel::isPageBreakPreview() const 178 { 179 return mnViewType == XML_pageBreakPreview; 180 } 181 182 sal_Int32 SheetViewModel::getNormalZoom() const 183 { 184 const sal_Int32& rnZoom = isPageBreakPreview() ? mnNormalZoom : mnCurrentZoom; 185 sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_NORMALZOOM_DEF; 186 return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); 187 } 188 189 sal_Int32 SheetViewModel::getPageBreakZoom() const 190 { 191 const sal_Int32& rnZoom = isPageBreakPreview() ? mnCurrentZoom : mnSheetLayoutZoom; 192 sal_Int32 nZoom = (rnZoom > 0) ? rnZoom : OOX_SHEETVIEW_SHEETLAYZOOM_DEF; 193 return getLimitedValue< sal_Int32 >( nZoom, API_ZOOMVALUE_MIN, API_ZOOMVALUE_MAX ); 194 } 195 196 sal_Int32 SheetViewModel::getGridColor( const FilterBase& rFilter ) const 197 { 198 return mbDefGridColor ? API_RGB_TRANSPARENT : maGridColor.getColor( rFilter.getGraphicHelper() ); 199 } 200 201 const PaneSelectionModel* SheetViewModel::getPaneSelection( sal_Int32 nPaneId ) const 202 { 203 return maPaneSelMap.get( nPaneId ).get(); 204 } 205 206 const PaneSelectionModel* SheetViewModel::getActiveSelection() const 207 { 208 return getPaneSelection( mnActivePaneId ); 209 } 210 211 PaneSelectionModel& SheetViewModel::createPaneSelection( sal_Int32 nPaneId ) 212 { 213 PaneSelectionModelMap::mapped_type& rxPaneSel = maPaneSelMap[ nPaneId ]; 214 if( !rxPaneSel ) 215 rxPaneSel.reset( new PaneSelectionModel ); 216 return *rxPaneSel; 217 } 218 219 // ---------------------------------------------------------------------------- 220 221 SheetViewSettings::SheetViewSettings( const WorksheetHelper& rHelper ) : 222 WorksheetHelper( rHelper ) 223 { 224 } 225 226 void SheetViewSettings::importSheetView( const AttributeList& rAttribs ) 227 { 228 SheetViewModel& rModel = *createSheetView(); 229 rModel.maGridColor.setIndexed( rAttribs.getInteger( XML_colorId, OOX_COLOR_WINDOWTEXT ) ); 230 rModel.maFirstPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false ); 231 rModel.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 ); 232 rModel.mnViewType = rAttribs.getToken( XML_view, XML_normal ); 233 rModel.mnCurrentZoom = rAttribs.getInteger( XML_zoomScale, 100 ); 234 rModel.mnNormalZoom = rAttribs.getInteger( XML_zoomScaleNormal, 0 ); 235 rModel.mnSheetLayoutZoom = rAttribs.getInteger( XML_zoomScaleSheetLayoutView, 0 ); 236 rModel.mnPageLayoutZoom = rAttribs.getInteger( XML_zoomScalePageLayoutView, 0 ); 237 rModel.mbSelected = rAttribs.getBool( XML_tabSelected, false ); 238 rModel.mbRightToLeft = rAttribs.getBool( XML_rightToLeft, false ); 239 rModel.mbDefGridColor = rAttribs.getBool( XML_defaultGridColor, true ); 240 rModel.mbShowFormulas = rAttribs.getBool( XML_showFormulas, false ); 241 rModel.mbShowGrid = rAttribs.getBool( XML_showGridLines, true ); 242 rModel.mbShowHeadings = rAttribs.getBool( XML_showRowColHeaders, true ); 243 rModel.mbShowZeros = rAttribs.getBool( XML_showZeros, true ); 244 rModel.mbShowOutline = rAttribs.getBool( XML_showOutlineSymbols, true ); 245 } 246 247 void SheetViewSettings::importPane( const AttributeList& rAttribs ) 248 { 249 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" ); 250 if( !maSheetViews.empty() ) 251 { 252 SheetViewModel& rModel = *maSheetViews.back(); 253 rModel.maSecondPos = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_topLeftCell, OUString() ), getSheetIndex(), false ); 254 rModel.mnActivePaneId = rAttribs.getToken( XML_activePane, XML_topLeft ); 255 rModel.mnPaneState = rAttribs.getToken( XML_state, XML_split ); 256 rModel.mfSplitX = rAttribs.getDouble( XML_xSplit, 0.0 ); 257 rModel.mfSplitY = rAttribs.getDouble( XML_ySplit, 0.0 ); 258 } 259 } 260 261 void SheetViewSettings::importSelection( const AttributeList& rAttribs ) 262 { 263 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" ); 264 if( !maSheetViews.empty() ) 265 { 266 // pane this selection belongs to 267 sal_Int32 nPaneId = rAttribs.getToken( XML_pane, XML_topLeft ); 268 PaneSelectionModel& rSelData = maSheetViews.back()->createPaneSelection( nPaneId ); 269 // cursor position 270 rSelData.maActiveCell = getAddressConverter().createValidCellAddress( rAttribs.getString( XML_activeCell, OUString() ), getSheetIndex(), false ); 271 rSelData.mnActiveCellId = rAttribs.getInteger( XML_activeCellId, 0 ); 272 // selection 273 rSelData.maSelection.clear(); 274 getAddressConverter().convertToCellRangeList( rSelData.maSelection, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), false ); 275 } 276 } 277 278 void SheetViewSettings::importChartSheetView( const AttributeList& rAttribs ) 279 { 280 SheetViewModel& rModel = *createSheetView(); 281 rModel.mnWorkbookViewId = rAttribs.getToken( XML_workbookViewId, 0 ); 282 rModel.mnCurrentZoom = rAttribs.getInteger( XML_zoomScale, 100 ); 283 rModel.mbSelected = rAttribs.getBool( XML_tabSelected, false ); 284 rModel.mbZoomToFit = rAttribs.getBool( XML_zoomToFit, false ); 285 } 286 287 void SheetViewSettings::importSheetView( SequenceInputStream& rStrm ) 288 { 289 SheetViewModel& rModel = *createSheetView(); 290 sal_uInt16 nFlags; 291 sal_Int32 nViewType; 292 BinAddress aFirstPos; 293 rStrm >> nFlags >> nViewType >> aFirstPos; 294 rModel.maGridColor.importColorId( rStrm ); 295 rModel.mnCurrentZoom = rStrm.readuInt16(); 296 rModel.mnNormalZoom = rStrm.readuInt16(); 297 rModel.mnSheetLayoutZoom = rStrm.readuInt16(); 298 rModel.mnPageLayoutZoom = rStrm.readuInt16(); 299 rStrm >> rModel.mnWorkbookViewId; 300 301 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 302 static const sal_Int32 spnViewTypes[] = { XML_normal, XML_pageBreakPreview, XML_pageLayout }; 303 rModel.mnViewType = STATIC_ARRAY_SELECT( spnViewTypes, nViewType, XML_normal ); 304 rModel.mbSelected = getFlag( nFlags, BIFF12_SHEETVIEW_SELECTED ); 305 rModel.mbRightToLeft = getFlag( nFlags, BIFF12_SHEETVIEW_RIGHTTOLEFT ); 306 rModel.mbDefGridColor = getFlag( nFlags, BIFF12_SHEETVIEW_DEFGRIDCOLOR ); 307 rModel.mbShowFormulas = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWFORMULAS ); 308 rModel.mbShowGrid = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWGRID ); 309 rModel.mbShowHeadings = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWHEADINGS ); 310 rModel.mbShowZeros = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWZEROS ); 311 rModel.mbShowOutline = getFlag( nFlags, BIFF12_SHEETVIEW_SHOWOUTLINE ); 312 } 313 314 void SheetViewSettings::importPane( SequenceInputStream& rStrm ) 315 { 316 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing sheet view model" ); 317 if( !maSheetViews.empty() ) 318 { 319 SheetViewModel& rModel = *maSheetViews.back(); 320 321 BinAddress aSecondPos; 322 sal_Int32 nActivePaneId; 323 sal_uInt8 nFlags; 324 rStrm >> rModel.mfSplitX >> rModel.mfSplitY >> aSecondPos >> nActivePaneId >> nFlags; 325 326 rModel.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); 327 rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); 328 rModel.mnPaneState = getFlagValue( nFlags, BIFF12_PANE_FROZEN, getFlagValue( nFlags, BIFF12_PANE_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); 329 } 330 } 331 332 void SheetViewSettings::importSelection( SequenceInputStream& rStrm ) 333 { 334 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importSelection - missing sheet view model" ); 335 if( !maSheetViews.empty() ) 336 { 337 // pane this selection belongs to 338 sal_Int32 nPaneId = rStrm.readInt32(); 339 PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) ); 340 // cursor position 341 BinAddress aActiveCell; 342 rStrm >> aActiveCell >> rPaneSel.mnActiveCellId; 343 rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); 344 // selection 345 BinRangeList aSelection; 346 rStrm >> aSelection; 347 rPaneSel.maSelection.clear(); 348 getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false ); 349 } 350 } 351 352 void SheetViewSettings::importChartSheetView( SequenceInputStream& rStrm ) 353 { 354 SheetViewModel& rModel = *createSheetView(); 355 sal_uInt16 nFlags; 356 rStrm >> nFlags >> rModel.mnCurrentZoom >> rModel.mnWorkbookViewId; 357 358 rModel.mbSelected = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_SELECTED ); 359 rModel.mbZoomToFit = getFlag( nFlags, BIFF12_CHARTSHEETVIEW_ZOOMTOFIT ); 360 } 361 362 void SheetViewSettings::importWindow2( BiffInputStream& rStrm ) 363 { 364 OSL_ENSURE( maSheetViews.empty(), "SheetViewSettings::importWindow2 - multiple WINDOW2 records" ); 365 SheetViewModel& rModel = *createSheetView(); 366 if( getBiff() == BIFF2 ) 367 { 368 rModel.mbShowFormulas = rStrm.readuInt8() != 0; 369 rModel.mbShowGrid = rStrm.readuInt8() != 0; 370 rModel.mbShowHeadings = rStrm.readuInt8() != 0; 371 rModel.mnPaneState = (rStrm.readuInt8() == 0) ? XML_split : XML_frozen; 372 rModel.mbShowZeros = rStrm.readuInt8() != 0; 373 BinAddress aFirstPos; 374 rStrm >> aFirstPos; 375 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 376 rModel.mbDefGridColor = rStrm.readuInt8() != 0; 377 rModel.maGridColor.importColorRgb( rStrm ); 378 } 379 else 380 { 381 sal_uInt16 nFlags; 382 BinAddress aFirstPos; 383 rStrm >> nFlags >> aFirstPos; 384 385 rModel.maFirstPos = getAddressConverter().createValidCellAddress( aFirstPos, getSheetIndex(), false ); 386 rModel.mnPaneState = getFlagValue( nFlags, BIFF_WINDOW2_FROZEN, getFlagValue( nFlags, BIFF_WINDOW2_FROZENNOSPLIT, XML_frozen, XML_frozenSplit ), XML_split ); 387 rModel.mbSelected = getFlag( nFlags, BIFF_WINDOW2_SELECTED ); 388 rModel.mbRightToLeft = getFlag( nFlags, BIFF_WINDOW2_RIGHTTOLEFT ); 389 rModel.mbDefGridColor = getFlag( nFlags, BIFF_WINDOW2_DEFGRIDCOLOR ); 390 rModel.mbShowFormulas = getFlag( nFlags, BIFF_WINDOW2_SHOWFORMULAS ); 391 rModel.mbShowGrid = getFlag( nFlags, BIFF_WINDOW2_SHOWGRID ); 392 rModel.mbShowHeadings = getFlag( nFlags, BIFF_WINDOW2_SHOWHEADINGS ); 393 rModel.mbShowZeros = getFlag( nFlags, BIFF_WINDOW2_SHOWZEROS ); 394 rModel.mbShowOutline = getFlag( nFlags, BIFF_WINDOW2_SHOWOUTLINE ); 395 396 if( getBiff() == BIFF8 ) 397 { 398 rModel.mnViewType = getFlagValue( nFlags, BIFF_WINDOW2_PAGEBREAKMODE, XML_pageBreakPreview, XML_normal ); 399 400 rModel.maGridColor.importColorId( rStrm ); 401 // zoom data not included in chart sheets 402 if( (getSheetType() != SHEETTYPE_CHARTSHEET) && (rStrm.getRemaining() >= 6) ) 403 { 404 rStrm.skip( 2 ); 405 sal_uInt16 nPageZoom, nNormalZoom; 406 rStrm >> nPageZoom >> nNormalZoom; 407 rModel.mnSheetLayoutZoom = nPageZoom; 408 rModel.mnNormalZoom = nNormalZoom; 409 } 410 } 411 else 412 { 413 rModel.maGridColor.importColorRgb( rStrm ); 414 } 415 } 416 } 417 418 void SheetViewSettings::importPane( BiffInputStream& rStrm ) 419 { 420 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); 421 if( !maSheetViews.empty() ) 422 { 423 sal_uInt8 nActivePaneId; 424 sal_uInt16 nSplitX, nSplitY; 425 BinAddress aSecondPos; 426 rStrm >> nSplitX >> nSplitY >> aSecondPos >> nActivePaneId; 427 428 SheetViewModel& rModel = *maSheetViews.back(); 429 rModel.mfSplitX = nSplitX; 430 rModel.mfSplitY = nSplitY; 431 rModel.maSecondPos = getAddressConverter().createValidCellAddress( aSecondPos, getSheetIndex(), false ); 432 rModel.mnActivePaneId = lclGetOoxPaneId( nActivePaneId, XML_topLeft ); 433 } 434 } 435 436 void SheetViewSettings::importScl( BiffInputStream& rStrm ) 437 { 438 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importScl - missing leading WINDOW2 record" ); 439 if( !maSheetViews.empty() ) 440 { 441 sal_uInt16 nNum, nDenom; 442 rStrm >> nNum >> nDenom; 443 OSL_ENSURE( nDenom > 0, "SheetViewSettings::importScl - invalid denominator" ); 444 if( nDenom > 0 ) 445 maSheetViews.back()->mnCurrentZoom = getLimitedValue< sal_Int32, sal_uInt16 >( (nNum * 100) / nDenom, 10, 400 ); 446 } 447 } 448 449 void SheetViewSettings::importSelection( BiffInputStream& rStrm ) 450 { 451 OSL_ENSURE( !maSheetViews.empty(), "SheetViewSettings::importPane - missing leading WINDOW2 record" ); 452 if( !maSheetViews.empty() ) 453 { 454 // pane this selection belongs to 455 sal_uInt8 nPaneId = rStrm.readuInt8(); 456 PaneSelectionModel& rPaneSel = maSheetViews.back()->createPaneSelection( lclGetOoxPaneId( nPaneId, -1 ) ); 457 // cursor position 458 BinAddress aActiveCell; 459 sal_uInt16 nActiveCellId; 460 rStrm >> aActiveCell >> nActiveCellId; 461 rPaneSel.maActiveCell = getAddressConverter().createValidCellAddress( aActiveCell, getSheetIndex(), false ); 462 rPaneSel.mnActiveCellId = nActiveCellId; 463 // selection 464 rPaneSel.maSelection.clear(); 465 BinRangeList aSelection; 466 aSelection.read( rStrm, false ); 467 getAddressConverter().convertToCellRangeList( rPaneSel.maSelection, aSelection, getSheetIndex(), false ); 468 } 469 } 470 471 void SheetViewSettings::finalizeImport() 472 { 473 // force creation of sheet view model to get the Excel defaults 474 SheetViewModelRef xModel = maSheetViews.empty() ? createSheetView() : maSheetViews.front(); 475 476 // #i59590# #158194# special handling for chart sheets (Excel ignores some settings in chart sheets) 477 if( getSheetType() == SHEETTYPE_CHARTSHEET ) 478 { 479 xModel->maPaneSelMap.clear(); 480 xModel->maFirstPos = xModel->maSecondPos = CellAddress( getSheetIndex(), 0, 0 ); 481 xModel->mnViewType = XML_normal; 482 xModel->mnActivePaneId = XML_topLeft; 483 xModel->mnPaneState = XML_split; 484 xModel->mfSplitX = xModel->mfSplitY = 0.0; 485 xModel->mbRightToLeft = false; 486 xModel->mbDefGridColor = true; 487 xModel->mbShowFormulas = false; 488 xModel->mbShowGrid = true; 489 xModel->mbShowHeadings = true; 490 xModel->mbShowZeros = true; 491 xModel->mbShowOutline = true; 492 } 493 494 // sheet selected (active sheet must be selected) 495 bool bSelected = xModel->mbSelected || (getSheetIndex() == getViewSettings().getActiveCalcSheet()); 496 497 // visible area and current cursor position (selection not supported via API) 498 CellAddress aFirstPos = xModel->maFirstPos; 499 const PaneSelectionModel* pPaneSel = xModel->getActiveSelection(); 500 CellAddress aCursor = pPaneSel ? pPaneSel->maActiveCell : aFirstPos; 501 502 // freeze/split position default 503 sal_Int16 nHSplitMode = API_SPLITMODE_NONE; 504 sal_Int16 nVSplitMode = API_SPLITMODE_NONE; 505 sal_Int32 nHSplitPos = 0; 506 sal_Int32 nVSplitPos = 0; 507 // active pane default 508 sal_Int16 nActivePane = API_SPLITPANE_BOTTOMLEFT; 509 510 // freeze/split position 511 if( (xModel->mnPaneState == XML_frozen) || (xModel->mnPaneState == XML_frozenSplit) ) 512 { 513 /* Frozen panes: handle split position as row/column positions. 514 #i35812# Excel uses number of visible rows/columns in the 515 frozen area (rows/columns scolled outside are not incuded), 516 Calc uses absolute position of first unfrozen row/column. */ 517 const CellAddress& rMaxApiPos = getAddressConverter().getMaxApiAddress(); 518 if( (xModel->mfSplitX >= 1.0) && (xModel->maFirstPos.Column + xModel->mfSplitX <= rMaxApiPos.Column) ) 519 nHSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Column + xModel->mfSplitX ); 520 nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; 521 if( (xModel->mfSplitY >= 1.0) && (xModel->maFirstPos.Row + xModel->mfSplitY <= rMaxApiPos.Row) ) 522 nVSplitPos = static_cast< sal_Int32 >( xModel->maFirstPos.Row + xModel->mfSplitY ); 523 nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_FREEZE : API_SPLITMODE_NONE; 524 } 525 else if( xModel->mnPaneState == XML_split ) 526 { 527 // split window: view settings API uses twips... 528 nHSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitX + 0.5, 0, SAL_MAX_INT32 ); 529 nHSplitMode = (nHSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; 530 nVSplitPos = getLimitedValue< sal_Int32, double >( xModel->mfSplitY + 0.5, 0, SAL_MAX_INT32 ); 531 nVSplitMode = (nVSplitPos > 0) ? API_SPLITMODE_SPLIT : API_SPLITMODE_NONE; 532 } 533 534 // active pane 535 switch( xModel->mnActivePaneId ) 536 { 537 // no horizontal split -> always use left panes 538 // no vertical split -> always use *bottom* panes 539 case XML_topLeft: 540 nActivePane = (nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT; 541 break; 542 case XML_topRight: 543 nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? 544 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_TOPLEFT) : 545 ((nVSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMRIGHT : API_SPLITPANE_TOPRIGHT); 546 break; 547 case XML_bottomLeft: 548 nActivePane = API_SPLITPANE_BOTTOMLEFT; 549 break; 550 case XML_bottomRight: 551 nActivePane = (nHSplitMode == API_SPLITMODE_NONE) ? API_SPLITPANE_BOTTOMLEFT : API_SPLITPANE_BOTTOMRIGHT; 552 break; 553 } 554 555 // write the sheet view settings into the property sequence 556 PropertyMap aPropMap; 557 aPropMap[ PROP_TableSelected ] <<= bSelected; 558 aPropMap[ PROP_CursorPositionX ] <<= aCursor.Column; 559 aPropMap[ PROP_CursorPositionY ] <<= aCursor.Row; 560 aPropMap[ PROP_HorizontalSplitMode ] <<= nHSplitMode; 561 aPropMap[ PROP_VerticalSplitMode ] <<= nVSplitMode; 562 aPropMap[ PROP_HorizontalSplitPositionTwips ] <<= nHSplitPos; 563 aPropMap[ PROP_VerticalSplitPositionTwips ] <<= nVSplitPos; 564 aPropMap[ PROP_ActiveSplitRange ] <<= nActivePane; 565 aPropMap[ PROP_PositionLeft ] <<= aFirstPos.Column; 566 aPropMap[ PROP_PositionTop ] <<= aFirstPos.Row; 567 aPropMap[ PROP_PositionRight ] <<= xModel->maSecondPos.Column; 568 aPropMap[ PROP_PositionBottom ] <<= ((nVSplitPos > 0) ? xModel->maSecondPos.Row : xModel->maFirstPos.Row); 569 aPropMap[ PROP_ZoomType ] <<= API_ZOOMTYPE_PERCENT; 570 aPropMap[ PROP_ZoomValue ] <<= static_cast< sal_Int16 >( xModel->getNormalZoom() ); 571 aPropMap[ PROP_PageViewZoomValue ] <<= static_cast< sal_Int16 >( xModel->getPageBreakZoom() ); 572 aPropMap[ PROP_GridColor ] <<= xModel->getGridColor( getBaseFilter() ); 573 aPropMap[ PROP_ShowPageBreakPreview ] <<= xModel->isPageBreakPreview(); 574 aPropMap[ PROP_ShowFormulas ] <<= xModel->mbShowFormulas; 575 aPropMap[ PROP_ShowGrid ] <<= xModel->mbShowGrid; 576 aPropMap[ PROP_HasColumnRowHeaders ] <<= xModel->mbShowHeadings; 577 aPropMap[ PROP_ShowZeroValues ] <<= xModel->mbShowZeros; 578 aPropMap[ PROP_IsOutlineSymbolsSet ] <<= xModel->mbShowOutline; 579 580 // store sheet view settings in global view settings object 581 getViewSettings().setSheetViewSettings( getSheetIndex(), xModel, Any( aPropMap.makePropertyValueSequence() ) ); 582 } 583 584 bool SheetViewSettings::isSheetRightToLeft() const 585 { 586 return !maSheetViews.empty() && maSheetViews.front()->mbRightToLeft; 587 } 588 589 // private -------------------------------------------------------------------- 590 591 SheetViewModelRef SheetViewSettings::createSheetView() 592 { 593 SheetViewModelRef xModel( new SheetViewModel ); 594 maSheetViews.push_back( xModel ); 595 return xModel; 596 } 597 598 // ============================================================================ 599 600 WorkbookViewModel::WorkbookViewModel() : 601 mnWinX( 0 ), 602 mnWinY( 0 ), 603 mnWinWidth( 0 ), 604 mnWinHeight( 0 ), 605 mnActiveSheet( 0 ), 606 mnFirstVisSheet( 0 ), 607 mnTabBarWidth( OOX_BOOKVIEW_TABBARRATIO_DEF ), 608 mnVisibility( XML_visible ), 609 mbShowTabBar( true ), 610 mbShowHorScroll( true ), 611 mbShowVerScroll( true ), 612 mbMinimized( false ) 613 { 614 } 615 616 // ---------------------------------------------------------------------------- 617 618 ViewSettings::ViewSettings( const WorkbookHelper& rHelper ) : 619 WorkbookHelper( rHelper ), 620 mbValidOleSize( false ) 621 { 622 } 623 624 void ViewSettings::importWorkbookView( const AttributeList& rAttribs ) 625 { 626 WorkbookViewModel& rModel = createWorkbookView(); 627 rModel.mnWinX = rAttribs.getInteger( XML_xWindow, 0 ); 628 rModel.mnWinY = rAttribs.getInteger( XML_yWindow, 0 ); 629 rModel.mnWinWidth = rAttribs.getInteger( XML_windowWidth, 0 ); 630 rModel.mnWinHeight = rAttribs.getInteger( XML_windowHeight, 0 ); 631 rModel.mnActiveSheet = rAttribs.getInteger( XML_activeTab, 0 ); 632 rModel.mnFirstVisSheet = rAttribs.getInteger( XML_firstSheet, 0 ); 633 rModel.mnTabBarWidth = rAttribs.getInteger( XML_tabRatio, 600 ); 634 rModel.mnVisibility = rAttribs.getToken( XML_visibility, XML_visible ); 635 rModel.mbShowTabBar = rAttribs.getBool( XML_showSheetTabs, true ); 636 rModel.mbShowHorScroll = rAttribs.getBool( XML_showHorizontalScroll, true ); 637 rModel.mbShowVerScroll = rAttribs.getBool( XML_showVerticalScroll, true ); 638 rModel.mbMinimized = rAttribs.getBool( XML_minimized, false ); 639 } 640 641 void ViewSettings::importOleSize( const AttributeList& rAttribs ) 642 { 643 OUString aRange = rAttribs.getString( XML_ref, OUString() ); 644 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aRange, 0, true, false ); 645 } 646 647 void ViewSettings::importWorkbookView( SequenceInputStream& rStrm ) 648 { 649 WorkbookViewModel& rModel = createWorkbookView(); 650 sal_uInt8 nFlags; 651 rStrm >> rModel.mnWinX >> rModel.mnWinY >> rModel.mnWinWidth >> rModel.mnWinHeight >> rModel.mnTabBarWidth >> rModel.mnFirstVisSheet >> rModel.mnActiveSheet >> nFlags; 652 rModel.mnVisibility = getFlagValue( nFlags, BIFF12_WBVIEW_HIDDEN, XML_hidden, XML_visible ); 653 rModel.mbShowTabBar = getFlag( nFlags, BIFF12_WBVIEW_SHOWTABBAR ); 654 rModel.mbShowHorScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWHORSCROLL ); 655 rModel.mbShowVerScroll = getFlag( nFlags, BIFF12_WBVIEW_SHOWVERSCROLL ); 656 rModel.mbMinimized = getFlag( nFlags, BIFF12_WBVIEW_MINIMIZED ); 657 } 658 659 void ViewSettings::importOleSize( SequenceInputStream& rStrm ) 660 { 661 BinRange aBinRange; 662 rStrm >> aBinRange; 663 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false ); 664 } 665 666 void ViewSettings::importWindow1( BiffInputStream& rStrm ) 667 { 668 sal_uInt16 nWinX, nWinY, nWinWidth, nWinHeight; 669 rStrm >> nWinX >> nWinY >> nWinWidth >> nWinHeight; 670 671 // WINDOW1 record occures in every sheet in BIFF4W 672 OSL_ENSURE( maBookViews.empty() || ((getBiff() == BIFF4) && isWorkbookFile()), 673 "ViewSettings::importWindow1 - multiple WINDOW1 records" ); 674 WorkbookViewModel& rModel = createWorkbookView(); 675 rModel.mnWinX = nWinX; 676 rModel.mnWinY = nWinY; 677 rModel.mnWinWidth = nWinWidth; 678 rModel.mnWinHeight = nWinHeight; 679 680 if( getBiff() <= BIFF4 ) 681 { 682 sal_uInt8 nHidden; 683 rStrm >> nHidden; 684 rModel.mnVisibility = (nHidden == 0) ? XML_visible : XML_hidden; 685 } 686 else 687 { 688 sal_uInt16 nFlags, nActiveTab, nFirstVisTab, nSelectCnt, nTabBarWidth; 689 rStrm >> nFlags >> nActiveTab >> nFirstVisTab >> nSelectCnt >> nTabBarWidth; 690 691 rModel.mnActiveSheet = nActiveTab; 692 rModel.mnFirstVisSheet = nFirstVisTab; 693 rModel.mnTabBarWidth = nTabBarWidth; 694 rModel.mnVisibility = getFlagValue( nFlags, BIFF_WINDOW1_HIDDEN, XML_hidden, XML_visible ); 695 rModel.mbMinimized = getFlag( nFlags, BIFF_WINDOW1_MINIMIZED ); 696 rModel.mbShowHorScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWHORSCROLL ); 697 rModel.mbShowVerScroll = getFlag( nFlags, BIFF_WINDOW1_SHOWVERSCROLL ); 698 rModel.mbShowTabBar = getFlag( nFlags, BIFF_WINDOW1_SHOWTABBAR ); 699 } 700 } 701 702 void ViewSettings::importOleSize( BiffInputStream& rStrm ) 703 { 704 rStrm.skip( 2 ); 705 BinRange aBinRange; 706 aBinRange.read( rStrm, false ); 707 mbValidOleSize = getAddressConverter().convertToCellRange( maOleSize, aBinRange, 0, true, false ); 708 } 709 710 void ViewSettings::setSheetViewSettings( sal_Int16 nSheet, const SheetViewModelRef& rxSheetView, const Any& rProperties ) 711 { 712 maSheetViews[ nSheet ] = rxSheetView; 713 maSheetProps[ nSheet ] = rProperties; 714 } 715 716 void ViewSettings::setSheetUsedArea( const CellRangeAddress& rUsedArea ) 717 { 718 maSheetUsedAreas[ rUsedArea.Sheet ] = rUsedArea; 719 } 720 721 void ViewSettings::finalizeImport() 722 { 723 const WorksheetBuffer& rWorksheets = getWorksheets(); 724 if( rWorksheets.getWorksheetCount() <= 0 ) return; 725 726 // force creation of workbook view model to get the Excel defaults 727 const WorkbookViewModel& rModel = maBookViews.empty() ? createWorkbookView() : *maBookViews.front(); 728 729 // show object mode is part of workbook settings 730 sal_Int16 nShowMode = getWorkbookSettings().getApiShowObjectMode(); 731 732 // view settings for all sheets 733 Reference< XNameContainer > xSheetsNC = ContainerHelper::createNameContainer( getBaseFilter().getComponentContext() ); 734 if( !xSheetsNC.is() ) return; 735 for( SheetPropertiesMap::const_iterator aIt = maSheetProps.begin(), aEnd = maSheetProps.end(); aIt != aEnd; ++aIt ) 736 ContainerHelper::insertByName( xSheetsNC, rWorksheets.getCalcSheetName( aIt->first ), aIt->second ); 737 738 // use active sheet to set sheet properties that are document-global in Calc 739 sal_Int16 nActiveSheet = getActiveCalcSheet(); 740 SheetViewModelRef& rxActiveSheetView = maSheetViews[ nActiveSheet ]; 741 OSL_ENSURE( rxActiveSheetView.get(), "ViewSettings::finalizeImport - missing active sheet view settings" ); 742 if( !rxActiveSheetView ) 743 rxActiveSheetView.reset( new SheetViewModel ); 744 745 Reference< XIndexContainer > xContainer = ContainerHelper::createIndexContainer( getBaseFilter().getComponentContext() ); 746 if( xContainer.is() ) try 747 { 748 PropertyMap aPropMap; 749 aPropMap[ PROP_Tables ] <<= xSheetsNC; 750 aPropMap[ PROP_ActiveTable ] <<= rWorksheets.getCalcSheetName( nActiveSheet ); 751 aPropMap[ PROP_HasHorizontalScrollBar ] <<= rModel.mbShowHorScroll; 752 aPropMap[ PROP_HasVerticalScrollBar ] <<= rModel.mbShowVerScroll; 753 aPropMap[ PROP_HasSheetTabs ] <<= rModel.mbShowTabBar; 754 aPropMap[ PROP_RelativeHorizontalTabbarWidth ] <<= double( rModel.mnTabBarWidth / 1000.0 ); 755 aPropMap[ PROP_ShowObjects ] <<= nShowMode; 756 aPropMap[ PROP_ShowCharts ] <<= nShowMode; 757 aPropMap[ PROP_ShowDrawing ] <<= nShowMode; 758 aPropMap[ PROP_GridColor ] <<= rxActiveSheetView->getGridColor( getBaseFilter() ); 759 aPropMap[ PROP_ShowPageBreakPreview ] <<= rxActiveSheetView->isPageBreakPreview(); 760 aPropMap[ PROP_ShowFormulas ] <<= rxActiveSheetView->mbShowFormulas; 761 aPropMap[ PROP_ShowGrid ] <<= rxActiveSheetView->mbShowGrid; 762 aPropMap[ PROP_HasColumnRowHeaders ] <<= rxActiveSheetView->mbShowHeadings; 763 aPropMap[ PROP_ShowZeroValues ] <<= rxActiveSheetView->mbShowZeros; 764 aPropMap[ PROP_IsOutlineSymbolsSet ] <<= rxActiveSheetView->mbShowOutline; 765 766 xContainer->insertByIndex( 0, Any( aPropMap.makePropertyValueSequence() ) ); 767 Reference< XIndexAccess > xIAccess( xContainer, UNO_QUERY_THROW ); 768 Reference< XViewDataSupplier > xViewDataSuppl( getDocument(), UNO_QUERY_THROW ); 769 xViewDataSuppl->setViewData( xIAccess ); 770 } 771 catch( Exception& ) 772 { 773 OSL_ENSURE( false, "ViewSettings::finalizeImport - cannot create document view settings" ); 774 } 775 776 /* Set visible area to be used if this document is an embedded OLE object. 777 #i44077# If a new OLE object is inserted from file, there is no OLESIZE 778 record in the Excel file. In this case, use the used area calculated 779 from file contents (used cells and drawing objects). */ 780 maOleSize.Sheet = nActiveSheet; 781 const CellRangeAddress* pVisibleArea = mbValidOleSize ? 782 &maOleSize : ContainerHelper::getMapElement( maSheetUsedAreas, nActiveSheet ); 783 if( pVisibleArea ) 784 { 785 // calculate the visible area in units of 1/100 mm 786 PropertySet aRangeProp( getCellRangeFromDoc( *pVisibleArea ) ); 787 Point aPos; 788 Size aSize; 789 if( aRangeProp.getProperty( aPos, PROP_Position ) && aRangeProp.getProperty( aSize, PROP_Size ) ) 790 { 791 // set the visible area as sequence of long at the media descriptor 792 Sequence< sal_Int32 > aWinExtent( 4 ); 793 aWinExtent[ 0 ] = aPos.X; 794 aWinExtent[ 1 ] = aPos.Y; 795 aWinExtent[ 2 ] = aPos.X + aSize.Width; 796 aWinExtent[ 3 ] = aPos.Y + aSize.Height; 797 getBaseFilter().getMediaDescriptor()[ CREATE_OUSTRING( "WinExtent" ) ] <<= aWinExtent; 798 } 799 } 800 } 801 802 sal_Int16 ViewSettings::getActiveCalcSheet() const 803 { 804 return maBookViews.empty() ? 0 : ::std::max< sal_Int16 >( getWorksheets().getCalcSheetIndex( maBookViews.front()->mnActiveSheet ), 0 ); 805 } 806 807 // private -------------------------------------------------------------------- 808 809 WorkbookViewModel& ViewSettings::createWorkbookView() 810 { 811 WorkbookViewModelRef xModel( new WorkbookViewModel ); 812 maBookViews.push_back( xModel ); 813 return *xModel; 814 } 815 816 // ============================================================================ 817 818 } // namespace xls 819 } // namespace oox 820