Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / excel / impop.cxx
blob5c0f1c8acadcd74979a7e14e918a3a289381215e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <imp_op.hxx>
23 #include <filter/msfilter/countryid.hxx>
25 #include <scitems.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <svx/svxids.hrc>
29 #include <svl/zforlist.hxx>
30 #include <unotools/configmgr.hxx>
31 #include <sal/log.hxx>
33 #include <sfx2/objsh.hxx>
34 #include <tools/urlobj.hxx>
35 #include <docuno.hxx>
37 #include <formulacell.hxx>
38 #include <document.hxx>
39 #include <globstr.hrc>
40 #include <scresid.hxx>
41 #include <global.hxx>
42 #include <olinetab.hxx>
43 #include <stlpool.hxx>
44 #include <viewopti.hxx>
45 #include <docoptio.hxx>
46 #include <scextopt.hxx>
47 #include <unonames.hxx>
48 #include <paramisc.hxx>
49 #include <colrowst.hxx>
50 #include <otlnbuff.hxx>
51 #include <xistyle.hxx>
53 #include <namebuff.hxx>
54 #include <xltools.hxx>
55 #include <xltable.hxx>
56 #include <xltracer.hxx>
57 #include <xihelper.hxx>
58 #include <xipage.hxx>
59 #include <xiview.hxx>
60 #include <xiescher.hxx>
61 #include <xicontent.hxx>
63 #include <excform.hxx>
64 #include <documentimport.hxx>
66 #if defined(_WIN32)
67 #include <math.h>
68 #endif
70 using namespace ::com::sun::star;
72 const double ImportExcel::fExcToTwips = TWIPS_PER_CHAR / 256.0;
74 ImportTyp::ImportTyp( ScDocument* pDoc, rtl_TextEncoding eQ )
76 eQuellChar = eQ;
77 pD = pDoc;
80 ImportTyp::~ImportTyp()
84 ImportExcel::ImportExcel( XclImpRootData& rImpData, SvStream& rStrm ):
85 ImportTyp( &rImpData.mrDoc, rImpData.meTextEnc ),
86 XclImpRoot( rImpData ),
87 maStrm( rStrm, GetRoot() ),
88 aIn( maStrm ),
89 maScOleSize( ScAddress::INITIALIZE_INVALID ),
90 pColOutlineBuff(nullptr),
91 pRowOutlineBuff(nullptr),
92 pColRowBuff(nullptr),
93 mpLastFormula(nullptr),
94 mnLastRefIdx( 0 ),
95 mnIxfeIndex( 0 ),
96 mnLastRecId(0),
97 mbBiff2HasXfs(false),
98 mbBiff2HasXfsValid(false)
100 nBdshtTab = 0;
102 // fill in root data - after new's without root as parameter
103 pExcRoot = &GetOldRoot();
104 pExcRoot->pIR = this; // ExcRoot -> XclImpRoot
105 pExcRoot->eDateiTyp = BiffX;
106 pExcRoot->pExtSheetBuff.reset( new ExtSheetBuffer( pExcRoot ) ); //&aExtSheetBuff;
107 pExcRoot->pShrfmlaBuff.reset( new SharedFormulaBuffer( pExcRoot ) ); //&aShrfrmlaBuff;
108 pExcRoot->pExtNameBuff.reset( new ExtNameBuff ( *this ) );
110 pOutlineListBuffer.reset(new XclImpOutlineListBuffer);
112 // from Biff8 on
113 pFormConv.reset(new ExcelToSc( GetRoot() ));
114 pExcRoot->pFmlaConverter = pFormConv.get();
116 bTabTruncated = false;
118 // Excel document per Default on 31.12.1899, accords to Excel settings with 1.1.1900
119 ScDocOptions aOpt = pD->GetDocOptions();
120 aOpt.SetDate( 30, 12, 1899 );
121 pD->SetDocOptions( aOpt );
122 pD->GetFormatTable()->ChangeNullDate( 30, 12, 1899 );
124 ScDocOptions aDocOpt( pD->GetDocOptions() );
125 aDocOpt.SetIgnoreCase( true ); // always in Excel
126 aDocOpt.SetFormulaRegexEnabled( false ); // regular expressions? what's that?
127 aDocOpt.SetFormulaWildcardsEnabled( true ); // Excel uses wildcard expressions
128 aDocOpt.SetLookUpColRowNames( false ); // default: no natural language refs
129 pD->SetDocOptions( aDocOpt );
132 ImportExcel::~ImportExcel()
134 GetDoc().SetSrcCharSet( GetTextEncoding() );
136 pOutlineListBuffer.reset();
138 pFormConv.reset();
141 void ImportExcel::SetLastFormula( SCCOL nCol, SCROW nRow, double fVal, sal_uInt16 nXF, ScFormulaCell* pCell )
143 LastFormulaMapType::iterator it = maLastFormulaCells.find(nCol);
144 if (it == maLastFormulaCells.end())
146 std::pair<LastFormulaMapType::iterator, bool> r =
147 maLastFormulaCells.emplace(nCol, LastFormula());
148 it = r.first;
151 it->second.mnCol = nCol;
152 it->second.mnRow = nRow;
153 it->second.mpCell = pCell;
154 it->second.mfValue = fVal;
155 it->second.mnXF = nXF;
157 mpLastFormula = &it->second;
160 void ImportExcel::ReadFileSharing()
162 sal_uInt16 nRecommendReadOnly, nPasswordHash;
163 nRecommendReadOnly = maStrm.ReaduInt16();
164 nPasswordHash = maStrm.ReaduInt16();
166 if( (nRecommendReadOnly != 0) || (nPasswordHash != 0) )
168 if( SfxItemSet* pItemSet = GetMedium().GetItemSet() )
169 pItemSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
171 if( SfxObjectShell* pShell = GetDocShell() )
173 if( nRecommendReadOnly != 0 )
174 pShell->SetLoadReadonly( true );
175 if( nPasswordHash != 0 )
176 pShell->SetModifyPasswordHash( nPasswordHash );
181 sal_uInt16 ImportExcel::ReadXFIndex( const ScAddress& rScPos, bool bBiff2 )
183 sal_uInt16 nXFIdx = 0;
184 if( bBiff2 )
186 /* #i71453# On first call, check if the file contains XF records (by
187 trying to access the first XF with index 0). If there are no XFs,
188 the explicit formatting information contained in each cell record
189 will be used instead. */
190 if( !mbBiff2HasXfsValid )
192 mbBiff2HasXfsValid = true;
193 mbBiff2HasXfs = GetXFBuffer().GetXF( 0 ) != nullptr;
195 // read formatting information (includes the XF identifier)
196 sal_uInt8 nFlags1, nFlags2, nFlags3;
197 nFlags1 = maStrm.ReaduInt8();
198 nFlags2 = maStrm.ReaduInt8();
199 nFlags3 = maStrm.ReaduInt8();
200 /* If the file contains XFs, extract and set the XF identifier,
201 otherwise get the explicit formatting. */
202 if( mbBiff2HasXfs )
204 nXFIdx = ::extract_value< sal_uInt16 >( nFlags1, 0, 6 );
205 /* If the identifier is equal to 63, then the real identifier is
206 contained in the preceding IXFE record (stored in mnBiff2XfId). */
207 if( nXFIdx == 63 )
208 nXFIdx = mnIxfeIndex;
210 else
212 /* Let the XclImpXF class do the conversion of the imported
213 formatting. The XF buffer is empty, therefore will not do any
214 conversion based on the XF index later on. */
215 XclImpXF::ApplyPatternForBiff2CellFormat( GetRoot(), rScPos, nFlags1, nFlags2, nFlags3 );
218 else
219 nXFIdx = aIn.ReaduInt16();
220 return nXFIdx;
223 void ImportExcel::ReadDimensions()
225 XclRange aXclUsedArea;
226 if( (maStrm.GetRecId() == EXC_ID2_DIMENSIONS) || (GetBiff() <= EXC_BIFF5) )
228 maStrm >> aXclUsedArea;
229 if( (aXclUsedArea.GetColCount() > 1) && (aXclUsedArea.GetRowCount() > 1) )
231 // Excel stores first unused row/column index
232 --aXclUsedArea.maLast.mnCol;
233 --aXclUsedArea.maLast.mnRow;
234 // create the Calc range
235 SCTAB nScTab = GetCurrScTab();
236 ScRange& rScUsedArea = GetExtDocOptions().GetOrCreateTabSettings( nScTab ).maUsedArea;
237 GetAddressConverter().ConvertRange( rScUsedArea, aXclUsedArea, nScTab, nScTab, false );
238 // if any error occurs in ConvertRange(), rScUsedArea keeps untouched
241 else
243 sal_uInt32 nXclRow1 = 0, nXclRow2 = 0;
244 nXclRow1 = maStrm.ReaduInt32();
245 nXclRow2 = maStrm.ReaduInt32();
246 aXclUsedArea.maFirst.mnCol = maStrm.ReaduInt16();
247 aXclUsedArea.maLast.mnCol = maStrm.ReaduInt16();
248 if( (nXclRow1 < nXclRow2) && (aXclUsedArea.GetColCount() > 1) &&
249 (nXclRow1 <= static_cast< sal_uInt32 >( GetScMaxPos().Row() )) )
251 // Excel stores first unused row/column index
252 --nXclRow2;
253 --aXclUsedArea.maLast.mnCol;
254 // convert row indexes to 16-bit values
255 aXclUsedArea.maFirst.mnRow = static_cast< sal_uInt16 >( nXclRow1 );
256 aXclUsedArea.maLast.mnRow = limit_cast< sal_uInt16 >( nXclRow2, aXclUsedArea.maFirst.mnRow, SAL_MAX_UINT16 );
257 // create the Calc range
258 SCTAB nScTab = GetCurrScTab();
259 ScRange& rScUsedArea = GetExtDocOptions().GetOrCreateTabSettings( nScTab ).maUsedArea;
260 GetAddressConverter().ConvertRange( rScUsedArea, aXclUsedArea, nScTab, nScTab, false );
261 // if any error occurs in ConvertRange(), rScUsedArea keeps untouched
266 void ImportExcel::ReadBlank()
268 XclAddress aXclPos;
269 aIn >> aXclPos;
271 ScAddress aScPos( ScAddress::UNINITIALIZED );
272 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
274 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BLANK );
276 GetXFRangeBuffer().SetBlankXF( aScPos, nXFIdx );
280 void ImportExcel::ReadInteger()
282 XclAddress aXclPos;
283 maStrm >> aXclPos;
285 ScAddress aScPos( ScAddress::UNINITIALIZED );
286 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
288 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, true );
289 sal_uInt16 nValue;
290 nValue = maStrm.ReaduInt16();
292 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
293 GetDocImport().setNumericCell(aScPos, nValue);
297 void ImportExcel::ReadNumber()
299 XclAddress aXclPos;
300 maStrm >> aXclPos;
302 ScAddress aScPos( ScAddress::UNINITIALIZED );
303 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
305 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_NUMBER );
306 double fValue;
307 fValue = maStrm.ReadDouble();
309 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
310 GetDocImport().setNumericCell(aScPos, fValue);
314 void ImportExcel::ReadLabel()
316 XclAddress aXclPos;
317 maStrm >> aXclPos;
319 ScAddress aScPos( ScAddress::UNINITIALIZED );
320 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
322 /* Record ID BIFF XF type String type
323 0x0004 2-7 3 byte 8-bit length, byte string
324 0x0004 8 3 byte 16-bit length, unicode string
325 0x0204 2-7 2 byte 16-bit length, byte string
326 0x0204 8 2 byte 16-bit length, unicode string */
327 bool bBiff2 = maStrm.GetRecId() == EXC_ID2_LABEL;
328 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, bBiff2 );
329 XclStrFlags nFlags = (bBiff2 && (GetBiff() <= EXC_BIFF5)) ? XclStrFlags::EightBitLength : XclStrFlags::NONE;
330 XclImpString aString;
332 // #i63105# use text encoding from FONT record
333 rtl_TextEncoding eOldTextEnc = GetTextEncoding();
334 if( const XclImpFont* pFont = GetXFBuffer().GetFont( nXFIdx ) )
335 SetTextEncoding( pFont->GetFontEncoding() );
336 aString.Read( maStrm, nFlags );
337 SetTextEncoding( eOldTextEnc );
339 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
340 XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, GetRoot(), aString, nXFIdx);
344 void ImportExcel::ReadBoolErr()
346 XclAddress aXclPos;
347 maStrm >> aXclPos;
349 ScAddress aScPos( ScAddress::UNINITIALIZED );
350 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
352 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BOOLERR );
353 sal_uInt8 nValue, nType;
354 nValue = maStrm.ReaduInt8();
355 nType = maStrm.ReaduInt8();
357 if( nType == EXC_BOOLERR_BOOL )
358 GetXFRangeBuffer().SetBoolXF( aScPos, nXFIdx );
359 else
360 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
362 double fValue;
363 std::unique_ptr<ScTokenArray> pScTokArr = ErrorToFormula( nType != EXC_BOOLERR_BOOL, nValue, fValue );
364 ScFormulaCell* pCell = pScTokArr
365 ? new ScFormulaCell(pD, aScPos, std::move(pScTokArr))
366 : new ScFormulaCell(pD, aScPos);
367 pCell->SetHybridDouble( fValue );
368 GetDocImport().setFormulaCell(aScPos, pCell);
372 void ImportExcel::ReadRk()
374 XclAddress aXclPos;
375 maStrm >> aXclPos;
377 ScAddress aScPos( ScAddress::UNINITIALIZED );
378 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
380 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, false );
381 sal_Int32 nRk;
382 nRk = maStrm.ReadInt32();
384 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
385 GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRk));
389 void ImportExcel::Window1()
391 GetDocViewSettings().ReadWindow1( maStrm );
394 void ImportExcel::Row25()
396 sal_uInt16 nRow, nRowHeight;
398 nRow = aIn.ReaduInt16();
399 aIn.Ignore( 4 );
401 if( ValidRow( nRow ) )
403 nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
404 aIn.Ignore( 2 );
406 if( GetBiff() == EXC_BIFF2 )
407 {// -------------------- BIFF2
408 pColRowBuff->SetHeight( nRow, nRowHeight );
410 else
411 {// -------------------- BIFF5
412 sal_uInt16 nGrbit;
414 aIn.Ignore( 2 ); // reserved
415 nGrbit = aIn.ReaduInt16();
417 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
418 pRowOutlineBuff->SetLevel( nRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
419 pColRowBuff->SetRowSettings( nRow, nRowHeight, nGrbit );
424 void ImportExcel::Bof2()
426 sal_uInt16 nSubType;
427 maStrm.DisableDecryption();
428 maStrm.Ignore( 2 );
429 nSubType = maStrm.ReaduInt16();
431 if( nSubType == 0x0020 ) // Chart
432 pExcRoot->eDateiTyp = Biff2C;
433 else if( nSubType == 0x0040 ) // Macro
434 pExcRoot->eDateiTyp = Biff2M;
435 else // #i51490# Excel interprets invalid indexes as worksheet
436 pExcRoot->eDateiTyp = Biff2;
439 void ImportExcel::Eof()
441 // POST: cannot be called after an invalid table!
442 EndSheet();
443 IncCurrScTab();
446 void ImportExcel::SheetPassword()
448 if (GetRoot().GetBiff() != EXC_BIFF8)
449 return;
451 GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
454 void ImportExcel::Externsheet()
456 OUString aUrl, aTabName;
457 bool bSameWorkBook;
458 OUString aEncodedUrl( aIn.ReadByteString( false ) );
459 XclImpUrlHelper::DecodeUrl( aUrl, aTabName, bSameWorkBook, *pExcRoot->pIR, aEncodedUrl );
460 mnLastRefIdx = pExcRoot->pExtSheetBuff->Add( aUrl, aTabName, bSameWorkBook );
463 void ImportExcel:: WinProtection()
465 if (GetRoot().GetBiff() != EXC_BIFF8)
466 return;
468 GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
471 void ImportExcel::Columndefault()
472 {// Default Cell Attributes
473 sal_uInt16 nColMic, nColMac;
474 sal_uInt8 nOpt0;
476 nColMic = aIn.ReaduInt16();
477 nColMac = aIn.ReaduInt16();
479 OSL_ENSURE( aIn.GetRecLeft() == static_cast<std::size_t>(nColMac - nColMic) * 3 + 2,
480 "ImportExcel::Columndefault - wrong record size" );
482 nColMac--;
484 if( nColMac > pD->MaxCol() )
485 nColMac = static_cast<sal_uInt16>(pD->MaxCol());
487 for( sal_uInt16 nCol = nColMic ; nCol <= nColMac ; nCol++ )
489 nOpt0 = aIn.ReaduInt8();
490 aIn.Ignore( 2 ); // only 0. Attribut-Byte used
492 if( nOpt0 & 0x80 ) // Col hidden?
493 pColRowBuff->HideCol( nCol );
497 void ImportExcel::Array25()
499 sal_uInt16 nFormLen;
500 sal_uInt16 nFirstRow = aIn.ReaduInt16();
501 sal_uInt16 nLastRow = aIn.ReaduInt16();
502 sal_uInt8 nFirstCol = aIn.ReaduInt8();
503 sal_uInt8 nLastCol = aIn.ReaduInt8();
505 if( GetBiff() == EXC_BIFF2 )
506 {// BIFF2
507 aIn.Ignore( 1 );
508 nFormLen = aIn.ReaduInt8();
510 else
511 {// BIFF5
512 aIn.Ignore( 6 );
513 nFormLen = aIn.ReaduInt16();
516 std::unique_ptr<ScTokenArray> pResult;
518 if (ValidColRow(nLastCol, nLastRow))
520 // the read mark is now on the formula, length in nFormLen
522 pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
523 static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
524 pFormConv->Convert(pResult, maStrm, nFormLen, true);
526 SAL_WARN_IF(!pResult, "sc", "*ImportExcel::Array25(): ScTokenArray is NULL!");
529 if (pResult)
531 ScDocumentImport& rDoc = GetDocImport();
532 ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
533 rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
537 void ImportExcel::Rec1904()
539 sal_uInt16 n1904;
541 n1904 = aIn.ReaduInt16();
543 if( n1904 )
544 {// 1904 date system
545 ScDocOptions aOpt = pD->GetDocOptions();
546 aOpt.SetDate( 1, 1, 1904 );
547 pD->SetDocOptions( aOpt );
548 pD->GetFormatTable()->ChangeNullDate( 1, 1, 1904 );
552 void ImportExcel::Externname25()
554 sal_uInt32 nRes;
555 sal_uInt16 nOpt;
557 nOpt = aIn.ReaduInt16();
558 nRes = aIn.ReaduInt32();
560 aIn.ReadByteString( false ); // name
562 if( ( nOpt & 0x0001 ) || ( ( nOpt & 0xFFFE ) == 0x0000 ) )
563 {// external name
564 pExcRoot->pExtNameBuff->AddName( mnLastRefIdx );
566 else if( nOpt & 0x0010 )
567 {// ole link
568 pExcRoot->pExtNameBuff->AddOLE( mnLastRefIdx, nRes ); // nRes is storage ID
570 else
571 {// dde link
572 pExcRoot->pExtNameBuff->AddDDE( mnLastRefIdx );
576 void ImportExcel::Colwidth()
577 {// Column Width
578 sal_uInt8 nColFirst, nColLast;
579 sal_uInt16 nColWidth;
581 nColFirst = aIn.ReaduInt8();
582 nColLast = aIn.ReaduInt8();
583 nColWidth = aIn.ReaduInt16();
585 //TODO: add a check for the unlikely case of changed MAXCOL (-> XclImpAddressConverter)
586 // if( nColLast > pD->MaxCol() )
587 // nColLast = static_cast<sal_uInt16>(pD->MaxCol());
589 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
590 pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
593 void ImportExcel::Defrowheight2()
595 sal_uInt16 nDefHeight;
596 nDefHeight = maStrm.ReaduInt16();
597 nDefHeight &= 0x7FFF;
598 pColRowBuff->SetDefHeight( nDefHeight, EXC_DEFROW_UNSYNCED );
601 void ImportExcel::SheetProtect()
603 if (GetRoot().GetBiff() != EXC_BIFF8)
604 return;
606 GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
609 void ImportExcel::DocProtect()
611 if (GetRoot().GetBiff() != EXC_BIFF8)
612 return;
614 GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
617 void ImportExcel::DocPasssword()
619 if (GetRoot().GetBiff() != EXC_BIFF8)
620 return;
622 GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
625 void ImportExcel::Codepage()
627 SetCodePage( maStrm.ReaduInt16() );
630 void ImportExcel::Ixfe()
632 mnIxfeIndex = maStrm.ReaduInt16();
635 void ImportExcel::DefColWidth()
637 // stored as entire characters -> convert to 1/256 of characters (as in COLINFO)
638 double fDefWidth = 256.0 * maStrm.ReaduInt16();
640 if (!pColRowBuff)
642 SAL_WARN("sc", "*ImportExcel::DefColWidth(): pColRowBuff is NULL!");
643 return;
646 // #i3006# additional space for default width - Excel adds space depending on font size
647 long nFontHt = GetFontBuffer().GetAppFontData().mnHeight;
648 fDefWidth += XclTools::GetXclDefColWidthCorrection( nFontHt );
650 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( limit_cast< sal_uInt16 >( fDefWidth ), GetCharWidth() );
651 pColRowBuff->SetDefWidth( nScWidth );
654 void ImportExcel::Colinfo()
655 {// Column Formatting Information
656 sal_uInt16 nColFirst, nColLast, nColWidth, nXF;
657 sal_uInt16 nOpt;
659 nColFirst = aIn.ReaduInt16();
660 nColLast = aIn.ReaduInt16();
661 nColWidth = aIn.ReaduInt16();
662 nXF = aIn.ReaduInt16();
663 nOpt = aIn.ReaduInt16();
665 if( nColFirst > pD->MaxCol() )
666 return;
668 if( nColLast > pD->MaxCol() )
669 nColLast = static_cast<sal_uInt16>(pD->MaxCol());
671 bool bHidden = ::get_flag( nOpt, EXC_COLINFO_HIDDEN );
672 bool bCollapsed = ::get_flag( nOpt, EXC_COLINFO_COLLAPSED );
673 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nOpt, 8, 3 );
674 pColOutlineBuff->SetLevelRange( nColFirst, nColLast, nLevel, bCollapsed );
676 if( bHidden )
677 pColRowBuff->HideColRange( nColFirst, nColLast );
679 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
680 pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
681 pColRowBuff->SetDefaultXF( nColFirst, nColLast, nXF );
684 void ImportExcel::Wsbool()
686 sal_uInt16 nFlags;
687 nFlags = aIn.ReaduInt16();
689 pRowOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_ROWBELOW ) );
690 pColOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_COLBELOW ) );
692 GetPageSettings().SetFitToPages( ::get_flag( nFlags, EXC_WSBOOL_FITTOPAGE ) );
695 void ImportExcel::Boundsheet()
697 sal_uInt16 nGrbit = 0;
699 if( GetBiff() == EXC_BIFF5 )
701 aIn.DisableDecryption();
702 maSheetOffsets.push_back( aIn.ReaduInt32() );
703 aIn.EnableDecryption();
704 nGrbit = aIn.ReaduInt16();
707 OUString aName( aIn.ReadByteString( false ) );
709 SCTAB nScTab = nBdshtTab;
710 if( nScTab > 0 )
712 OSL_ENSURE( !pD->HasTable( nScTab ), "ImportExcel::Boundsheet - sheet exists already" );
713 pD->MakeTable( nScTab );
716 if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
717 pD->SetVisible( nScTab, false );
719 if( !pD->RenameTab( nScTab, aName ) )
721 pD->CreateValidTabName( aName );
722 pD->RenameTab( nScTab, aName );
725 nBdshtTab++;
728 void ImportExcel::Country()
730 sal_uInt16 nUICountry, nDocCountry;
731 nUICountry = maStrm.ReaduInt16();
732 nDocCountry = maStrm.ReaduInt16();
734 // Store system language in XclRoot
735 LanguageType eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nDocCountry ) );
736 if( eLanguage != LANGUAGE_DONTKNOW )
737 SetDocLanguage( eLanguage );
739 // Set Excel UI language in add-in name translator
740 eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nUICountry ) );
741 if( eLanguage != LANGUAGE_DONTKNOW )
742 SetUILanguage( eLanguage );
745 void ImportExcel::ReadUsesElfs()
747 if( maStrm.ReaduInt16() != 0 )
749 ScDocOptions aDocOpt = GetDoc().GetDocOptions();
750 aDocOpt.SetLookUpColRowNames( true );
751 GetDoc().SetDocOptions( aDocOpt );
755 void ImportExcel::Hideobj()
757 sal_uInt16 nHide;
758 ScVObjMode eOle, eChart, eDraw;
760 nHide = aIn.ReaduInt16();
762 ScViewOptions aOpts( pD->GetViewOptions() );
764 switch( nHide )
766 case 1: // Placeholders
767 eOle = VOBJ_MODE_SHOW; // in Excel 97 only charts as place holder are displayed
768 eChart = VOBJ_MODE_SHOW; //#i80528# VOBJ_MODE_DUMMY replaced by VOBJ_MODE_SHOW now
769 eDraw = VOBJ_MODE_SHOW;
770 break;
771 case 2: // Hide all
772 eOle = VOBJ_MODE_HIDE;
773 eChart = VOBJ_MODE_HIDE;
774 eDraw = VOBJ_MODE_HIDE;
775 break;
776 default: // Show all
777 eOle = VOBJ_MODE_SHOW;
778 eChart = VOBJ_MODE_SHOW;
779 eDraw = VOBJ_MODE_SHOW;
780 break;
783 aOpts.SetObjMode( VOBJ_TYPE_OLE, eOle );
784 aOpts.SetObjMode( VOBJ_TYPE_CHART, eChart );
785 aOpts.SetObjMode( VOBJ_TYPE_DRAW, eDraw );
787 pD->SetViewOptions( aOpts );
790 void ImportExcel::Standardwidth()
792 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( maStrm.ReaduInt16(), GetCharWidth() );
793 if (!pColRowBuff)
795 SAL_WARN("sc", "*ImportExcel::Standardwidth(): pColRowBuff is NULL!");
796 return;
798 pColRowBuff->SetDefWidth( nScWidth, true );
801 void ImportExcel::Shrfmla()
803 switch (mnLastRecId)
805 case EXC_ID2_FORMULA:
806 case EXC_ID3_FORMULA:
807 case EXC_ID4_FORMULA:
808 // This record MUST immediately follow a FORMULA record.
809 break;
810 default:
811 return;
814 if (!mpLastFormula)
815 // The last FORMULA record should have left this data.
816 return;
818 aIn.Ignore( 8 );
819 sal_uInt16 nLenExpr = aIn.ReaduInt16();
821 // read mark is now on the formula
823 std::unique_ptr<ScTokenArray> pResult;
825 // The shared range in this record is erroneous more than half the time.
826 // Don't ever rely on it. Use the one from the formula cell above.
827 SCCOL nCol1 = mpLastFormula->mnCol;
828 SCROW nRow1 = mpLastFormula->mnRow;
830 ScAddress aPos(nCol1, nRow1, GetCurrScTab());
831 pFormConv->Reset(aPos);
832 pFormConv->Convert( pResult, maStrm, nLenExpr, true, FT_SharedFormula );
834 if (!pResult)
836 SAL_WARN("sc", "+ImportExcel::Shrfmla(): ScTokenArray is NULL!");
837 return;
840 pExcRoot->pShrfmlaBuff->Store(aPos, *pResult);
842 // Create formula cell for the last formula record.
844 ScDocumentImport& rDoc = GetDocImport();
846 ScFormulaCell* pCell = new ScFormulaCell(pD, aPos, std::move(pResult));
847 pCell->GetCode()->WrapReference(aPos, EXC_MAXCOL8, EXC_MAXROW8);
848 rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode());
849 rDoc.getDoc().EnsureTable(aPos.Tab());
850 rDoc.setFormulaCell(aPos, pCell);
851 pCell->SetNeedNumberFormat(false);
852 if (rtl::math::isFinite(mpLastFormula->mfValue))
853 pCell->SetResultDouble(mpLastFormula->mfValue);
855 GetXFRangeBuffer().SetXF(aPos, mpLastFormula->mnXF);
856 mpLastFormula->mpCell = pCell;
859 void ImportExcel::Mulrk()
861 XclAddress aXclPos;
862 sal_uInt16 nXF;
863 sal_Int32 nRkNum;
865 aIn >> aXclPos;
867 for( XclAddress aCurrXclPos( aXclPos ); (aXclPos.mnCol <= aCurrXclPos.mnCol) && (aIn.GetRecLeft() > 2); ++aCurrXclPos.mnCol )
869 nXF = aIn.ReaduInt16();
870 nRkNum = aIn.ReadInt32();
872 ScAddress aScPos( ScAddress::UNINITIALIZED );
873 if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
875 GetXFRangeBuffer().SetXF( aScPos, nXF );
876 GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRkNum));
881 void ImportExcel::Mulblank()
883 XclAddress aXclPos;
884 sal_uInt16 nXF;
886 aIn >> aXclPos;
888 for( XclAddress aCurrXclPos( aXclPos ); (aXclPos.mnCol <= aCurrXclPos.mnCol) && (aIn.GetRecLeft() > 2); ++aCurrXclPos.mnCol )
890 nXF = aIn.ReaduInt16();
892 ScAddress aScPos( ScAddress::UNINITIALIZED );
893 if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
894 GetXFRangeBuffer().SetBlankXF( aScPos, nXF );
898 void ImportExcel::Rstring()
900 XclAddress aXclPos;
901 sal_uInt16 nXFIdx;
902 aIn >> aXclPos;
903 nXFIdx = aIn.ReaduInt16();
905 ScAddress aScPos( ScAddress::UNINITIALIZED );
906 if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
908 // unformatted Unicode string with separate formatting information
909 XclImpString aString;
911 // #i63105# use text encoding from FONT record
912 rtl_TextEncoding eOldTextEnc = GetTextEncoding();
913 if( const XclImpFont* pFont = GetXFBuffer().GetFont( nXFIdx ) )
914 SetTextEncoding( pFont->GetFontEncoding() );
915 aString.Read( maStrm );
916 SetTextEncoding( eOldTextEnc );
918 // character formatting runs
919 if( !aString.IsRich() )
920 aString.ReadFormats( maStrm );
922 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
923 XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, aString, nXFIdx);
927 void ImportExcel::Cellmerging()
929 XclImpAddressConverter& rAddrConv = GetAddressConverter();
930 SCTAB nScTab = GetCurrScTab();
932 sal_uInt16 nCount;
933 nCount = maStrm.ReaduInt16();
934 for( sal_uInt16 nIdx = 0; (nIdx < nCount) && (maStrm.GetRecLeft() >= 8); ++nIdx )
936 XclRange aXclRange;
937 maStrm >> aXclRange; // 16-bit rows and columns
938 ScRange aScRange( ScAddress::UNINITIALIZED );
939 if( rAddrConv.ConvertRange( aScRange, aXclRange, nScTab, nScTab, true ) )
940 GetXFRangeBuffer().SetMerge( aScRange.aStart.Col(), aScRange.aStart.Row(), aScRange.aEnd.Col(), aScRange.aEnd.Row() );
944 void ImportExcel::Olesize()
946 XclRange aXclOleSize( ScAddress::UNINITIALIZED );
947 maStrm.Ignore( 2 );
948 aXclOleSize.Read( maStrm, false );
950 SCTAB nScTab = GetCurrScTab();
951 GetAddressConverter().ConvertRange( maScOleSize, aXclOleSize, nScTab, nScTab, false );
954 void ImportExcel::Row34()
956 sal_uInt16 nRow, nRowHeight, nGrbit, nXF;
958 nRow = aIn.ReaduInt16();
959 aIn.Ignore( 4 );
961 SCROW nScRow = static_cast< SCROW >( nRow );
963 if( ValidRow( nScRow ) )
965 nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
966 aIn.Ignore( 4 );
968 nRowHeight = nRowHeight & 0x7FFF; // Bit 15: Row Height not changed manually
969 if( !nRowHeight )
970 nRowHeight = (GetBiff() == EXC_BIFF2) ? 0x25 : 0x225;
972 nGrbit = aIn.ReaduInt16();
973 nXF = aIn.ReaduInt16();
975 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
976 pRowOutlineBuff->SetLevel( nScRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
977 pColRowBuff->SetRowSettings( nScRow, nRowHeight, nGrbit );
979 if( nGrbit & EXC_ROW_USEDEFXF )
980 GetXFRangeBuffer().SetRowDefXF( nScRow, nXF & EXC_ROW_XFMASK );
984 void ImportExcel::Bof3()
986 sal_uInt16 nSubType;
987 maStrm.DisableDecryption();
988 maStrm.Ignore( 2 );
989 nSubType = maStrm.ReaduInt16();
991 OSL_ENSURE( nSubType != 0x0100, "*ImportExcel::Bof3(): Biff3 as Workbook?!" );
992 if( nSubType == 0x0100 ) // Book
993 pExcRoot->eDateiTyp = Biff3W;
994 else if( nSubType == 0x0020 ) // Chart
995 pExcRoot->eDateiTyp = Biff3C;
996 else if( nSubType == 0x0040 ) // Macro
997 pExcRoot->eDateiTyp = Biff3M;
998 else // #i51490# Excel interprets invalid indexes as worksheet
999 pExcRoot->eDateiTyp = Biff3;
1002 void ImportExcel::Array34()
1004 sal_uInt16 nFirstRow, nLastRow, nFormLen;
1005 sal_uInt8 nFirstCol, nLastCol;
1007 nFirstRow = aIn.ReaduInt16();
1008 nLastRow = aIn.ReaduInt16();
1009 nFirstCol = aIn.ReaduInt8();
1010 nLastCol = aIn.ReaduInt8();
1011 aIn.Ignore( (GetBiff() >= EXC_BIFF5) ? 6 : 2 );
1012 nFormLen = aIn.ReaduInt16();
1014 std::unique_ptr<ScTokenArray> pResult;
1016 if( ValidColRow( nLastCol, nLastRow ) )
1018 // the read mark is now on the formula, length in nFormLen
1020 pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
1021 static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
1022 pFormConv->Convert( pResult, maStrm, nFormLen, true );
1024 SAL_WARN_IF(!pResult, "sc", "+ImportExcel::Array34(): ScTokenArray is NULL!");
1027 if (pResult)
1029 ScDocumentImport& rDoc = GetDocImport();
1030 ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
1031 rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
1035 void ImportExcel::Defrowheight345()
1037 sal_uInt16 nFlags, nDefHeight;
1038 nFlags = maStrm.ReaduInt16();
1039 nDefHeight = maStrm.ReaduInt16();
1041 if (!pColRowBuff)
1043 SAL_WARN("sc", "*ImportExcel::Defrowheight345(): pColRowBuff is NULL!");
1044 return;
1047 pColRowBuff->SetDefHeight( nDefHeight, nFlags );
1050 void ImportExcel::TableOp()
1052 sal_uInt16 nFirstRow, nLastRow;
1053 sal_uInt8 nFirstCol, nLastCol;
1054 sal_uInt16 nGrbit;
1055 sal_uInt16 nInpRow, nInpCol, nInpRow2, nInpCol2;
1057 nFirstRow = aIn.ReaduInt16();
1058 nLastRow = aIn.ReaduInt16();
1059 nFirstCol = aIn.ReaduInt8();
1060 nLastCol = aIn.ReaduInt8();
1061 nGrbit = aIn.ReaduInt16();
1062 nInpRow = aIn.ReaduInt16();
1063 nInpCol = aIn.ReaduInt16();
1064 nInpRow2 = aIn.ReaduInt16();
1065 nInpCol2 = aIn.ReaduInt16();
1067 if (utl::ConfigManager::IsFuzzing())
1069 //shrink to smallish arbitrary value to not timeout
1070 nLastRow = std::min<sal_uInt16>(nLastRow, MAXROW_30);
1073 if( ValidColRow( nLastCol, nLastRow ) )
1075 if( nFirstCol && nFirstRow )
1077 ScTabOpParam aTabOpParam;
1078 aTabOpParam.meMode = (nGrbit & EXC_TABLEOP_BOTH) ? ScTabOpParam::Both : ((nGrbit & EXC_TABLEOP_ROW) ? ScTabOpParam::Row : ScTabOpParam::Column);
1079 sal_uInt16 nCol = nFirstCol - 1;
1080 sal_uInt16 nRow = nFirstRow - 1;
1081 SCTAB nTab = GetCurrScTab();
1082 switch (aTabOpParam.meMode)
1084 case ScTabOpParam::Column:
1085 aTabOpParam.aRefFormulaCell.Set(
1086 static_cast<SCCOL>(nFirstCol),
1087 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1088 false, false );
1089 aTabOpParam.aRefFormulaEnd.Set(
1090 static_cast<SCCOL>(nLastCol),
1091 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1092 false, false );
1093 aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol),
1094 static_cast<SCROW>(nInpRow), nTab, false, false,
1095 false );
1096 nRow++;
1097 break;
1098 case ScTabOpParam::Row:
1099 aTabOpParam.aRefFormulaCell.Set(
1100 static_cast<SCCOL>(nFirstCol - 1),
1101 static_cast<SCROW>(nFirstRow), nTab, false, false,
1102 false );
1103 aTabOpParam.aRefFormulaEnd.Set(
1104 static_cast<SCCOL>(nFirstCol - 1),
1105 static_cast<SCROW>(nLastRow), nTab, false, false,
1106 false );
1107 aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1108 static_cast<SCROW>(nInpRow), nTab, false, false,
1109 false );
1110 nCol++;
1111 break;
1112 case ScTabOpParam::Both: // TWO-INPUT
1113 aTabOpParam.aRefFormulaCell.Set(
1114 static_cast<SCCOL>(nFirstCol - 1),
1115 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1116 false, false );
1117 aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1118 static_cast<SCROW>(nInpRow), nTab, false, false,
1119 false );
1120 aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol2),
1121 static_cast<SCROW>(nInpRow2), nTab, false, false,
1122 false );
1123 break;
1126 ScDocumentImport& rDoc = GetDocImport();
1127 ScRange aTabOpRange(nCol, nRow, nTab, nLastCol, nLastRow, nTab);
1128 rDoc.setTableOpCells(aTabOpRange, aTabOpParam);
1131 else
1133 bTabTruncated = true;
1134 GetTracer().TraceInvalidRow(nLastRow, pD->MaxRow());
1138 void ImportExcel::Bof4()
1140 sal_uInt16 nSubType;
1141 maStrm.DisableDecryption();
1142 maStrm.Ignore( 2 );
1143 nSubType = maStrm.ReaduInt16();
1145 if( nSubType == 0x0100 ) // Book
1146 pExcRoot->eDateiTyp = Biff4W;
1147 else if( nSubType == 0x0020 ) // Chart
1148 pExcRoot->eDateiTyp = Biff4C;
1149 else if( nSubType == 0x0040 ) // Macro
1150 pExcRoot->eDateiTyp = Biff4M;
1151 else // #i51490# Excel interprets invalid indexes as worksheet
1152 pExcRoot->eDateiTyp = Biff4;
1155 void ImportExcel::Bof5()
1157 //POST: eDateiTyp = Type of the file to be read
1158 sal_uInt16 nSubType, nVers;
1159 BiffTyp eDatei;
1161 maStrm.DisableDecryption();
1162 nVers = maStrm.ReaduInt16();
1163 nSubType = maStrm.ReaduInt16( );
1165 switch( nSubType )
1167 case 0x0005: eDatei = Biff5W; break; // workbook globals
1168 case 0x0006: eDatei = Biff5V; break; // VB module
1169 case 0x0010: eDatei = Biff5; break; // worksheet
1170 case 0x0020: eDatei = Biff5C; break; // chart
1171 case 0x0040: eDatei = Biff5M4; break; // macro sheet
1172 default:
1173 pExcRoot->eDateiTyp = BiffX;
1174 return;
1177 if( nVers == 0x0600 && (GetBiff() == EXC_BIFF8) )
1178 eDatei = static_cast<BiffTyp>( eDatei - Biff5 + Biff8 );
1180 pExcRoot->eDateiTyp = eDatei;
1183 void ImportExcel::EndSheet()
1185 pExcRoot->pExtSheetBuff->Reset();
1187 if( GetBiff() <= EXC_BIFF5 )
1189 pExcRoot->pExtNameBuff->Reset();
1190 mnLastRefIdx = 0;
1193 FinalizeTable();
1196 void ImportExcel::NewTable()
1198 SCTAB nTab = GetCurrScTab();
1199 if( nTab > 0 && !pD->HasTable( nTab ) )
1200 pD->MakeTable( nTab );
1202 if (nTab == 0 && GetBiff() == EXC_BIFF2)
1204 // For Excel 2.1 Worksheet file, we need to set the file name as the
1205 // sheet name.
1206 INetURLObject aURL(GetDocUrl());
1207 pD->RenameTab(0, aURL.getBase());
1210 pExcRoot->pShrfmlaBuff->Clear();
1211 maLastFormulaCells.clear();
1212 mpLastFormula = nullptr;
1214 InitializeTable( nTab );
1216 XclImpOutlineDataBuffer* pNewItem = new XclImpOutlineDataBuffer( GetRoot(), nTab );
1217 pOutlineListBuffer->push_back( std::unique_ptr<XclImpOutlineDataBuffer>(pNewItem) );
1218 pExcRoot->pColRowBuff = pColRowBuff = pNewItem->GetColRowBuff();
1219 pColOutlineBuff = pNewItem->GetColOutline();
1220 pRowOutlineBuff = pNewItem->GetRowOutline();
1223 std::unique_ptr<ScTokenArray> ImportExcel::ErrorToFormula( bool bErrOrVal, sal_uInt8 nError, double& rVal )
1225 return pFormConv->GetBoolErr( XclTools::ErrorToEnum( rVal, bErrOrVal, nError ) );
1228 void ImportExcel::AdjustRowHeight()
1230 /* Speed up chart import: import all sheets without charts, then
1231 update row heights (here), last load all charts -> do not any longer
1232 update inside of ScDocShell::ConvertFrom() (causes update of existing
1233 charts during each and every change of row height). */
1234 if( ScModelObj* pDocObj = GetDocModelObj() )
1235 pDocObj->UpdateAllRowHeights();
1238 void ImportExcel::PostDocLoad()
1240 /* Set automatic page numbering in Default page style (default is "page number = 1").
1241 Otherwise hidden tables (i.e. for scenarios) which have Default page style will
1242 break automatic page numbering. */
1243 if( SfxStyleSheetBase* pStyleSheet = GetStyleSheetPool().Find( ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Page ) )
1244 pStyleSheet->GetItemSet().Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 0 ) );
1246 // outlines for all sheets, sets hidden rows and columns (#i11776# after filtered ranges)
1247 for (auto& rxBuffer : *pOutlineListBuffer)
1248 rxBuffer->Convert();
1250 // document view settings (before visible OLE area)
1251 GetDocViewSettings().Finalize();
1253 // process all drawing objects (including OLE, charts, controls; after hiding rows/columns; before visible OLE area)
1254 GetObjectManager().ConvertObjects();
1256 // visible area (used if this document is an embedded OLE object)
1257 if( SfxObjectShell* pDocShell = GetDocShell() )
1259 // visible area if embedded
1260 const ScExtDocSettings& rDocSett = GetExtDocOptions().GetDocSettings();
1261 SCTAB nDisplScTab = rDocSett.mnDisplTab;
1263 /* #i44077# If a new OLE object is inserted from file, there is no
1264 OLESIZE record in the Excel file. Calculate used area from file
1265 contents (used cells and drawing objects). */
1266 if( !maScOleSize.IsValid() )
1268 // used area of displayed sheet (cell contents)
1269 if( const ScExtTabSettings* pTabSett = GetExtDocOptions().GetTabSettings( nDisplScTab ) )
1270 maScOleSize = pTabSett->maUsedArea;
1271 // add all valid drawing objects
1272 ScRange aScObjArea = GetObjectManager().GetUsedArea( nDisplScTab );
1273 if( aScObjArea.IsValid() )
1274 maScOleSize.ExtendTo( aScObjArea );
1277 // valid size found - set it at the document
1278 if( maScOleSize.IsValid() )
1280 pDocShell->SetVisArea( GetDoc().GetMMRect(
1281 maScOleSize.aStart.Col(), maScOleSize.aStart.Row(),
1282 maScOleSize.aEnd.Col(), maScOleSize.aEnd.Row(), nDisplScTab ) );
1283 GetDoc().SetVisibleTab( nDisplScTab );
1287 // open forms in alive mode (has no effect, if no controls in document)
1288 if( ScModelObj* pDocObj = GetDocModelObj() )
1289 pDocObj->setPropertyValue( SC_UNO_APPLYFMDES, uno::Any( false ) );
1291 // enables extended options to be set to the view after import
1292 GetExtDocOptions().SetChanged( true );
1294 // root data owns the extended document options -> create a new object
1295 GetDoc().SetExtDocOptions( std::make_unique<ScExtDocOptions>( GetExtDocOptions() ) );
1297 const SCTAB nLast = pD->GetTableCount();
1298 const ScRange* p;
1300 if( pExcRoot->pPrintRanges->HasRanges() )
1302 for( SCTAB n = 0 ; n < nLast ; n++ )
1304 p = pExcRoot->pPrintRanges->First(n);
1305 if( p )
1307 pD->ClearPrintRanges( n );
1308 while( p )
1310 pD->AddPrintRange( n, *p );
1311 p = pExcRoot->pPrintRanges->Next();
1314 else
1316 // #i4063# no print ranges -> print entire sheet
1317 pD->SetPrintEntireSheet( n );
1320 GetTracer().TracePrintRange();
1323 if( pExcRoot->pPrintTitles->HasRanges() )
1325 for( SCTAB n = 0 ; n < nLast ; n++ )
1327 p = pExcRoot->pPrintTitles->First(n);
1328 if( p )
1330 bool bRowVirgin = true;
1331 bool bColVirgin = true;
1333 while( p )
1335 if( p->aStart.Col() == 0 && p->aEnd.Col() == pD->MaxCol() && bRowVirgin )
1337 pD->SetRepeatRowRange( n, std::unique_ptr<ScRange>(new ScRange(*p)) );
1338 bRowVirgin = false;
1341 if( p->aStart.Row() == 0 && p->aEnd.Row() == pD->MaxRow() && bColVirgin )
1343 pD->SetRepeatColRange( n, std::unique_ptr<ScRange>(new ScRange(*p)) );
1344 bColVirgin = false;
1347 p = pExcRoot->pPrintTitles->Next();
1354 XclImpOutlineDataBuffer::XclImpOutlineDataBuffer( const XclImpRoot& rRoot, SCTAB nScTab ) :
1355 XclImpRoot( rRoot ),
1356 mxColOutlineBuff( new XclImpOutlineBuffer( rRoot.GetXclMaxPos().Col() + 1 ) ),
1357 mxRowOutlineBuff( new XclImpOutlineBuffer( rRoot.GetXclMaxPos().Row() + 1 ) ),
1358 mxColRowBuff( new XclImpColRowSettings( rRoot ) ),
1359 mnScTab( nScTab )
1363 XclImpOutlineDataBuffer::~XclImpOutlineDataBuffer()
1367 void XclImpOutlineDataBuffer::Convert()
1369 mxColOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetColArray() );
1370 mxColOutlineBuff->MakeScOutline();
1372 mxRowOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetRowArray() );
1373 mxRowOutlineBuff->MakeScOutline();
1375 mxColRowBuff->ConvertHiddenFlags( mnScTab );
1378 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */