use insert function instead of for loop
[LibreOffice.git] / sc / source / filter / excel / impop.cxx
blob4263f5deb9c7e2c8accc01c6e0ea3d3a5271ad27
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 <o3tl/safeint.hxx>
28 #include <sfx2/docfile.hxx>
29 #include <svx/svxids.hrc>
30 #include <svl/numformat.hxx>
31 #include <comphelper/configuration.hxx>
32 #include <sal/log.hxx>
34 #include <sfx2/objsh.hxx>
35 #include <tools/urlobj.hxx>
36 #include <docuno.hxx>
37 #include <docsh.hxx>
39 #include <formulacell.hxx>
40 #include <document.hxx>
41 #include <globstr.hrc>
42 #include <scresid.hxx>
43 #include <global.hxx>
44 #include <olinetab.hxx>
45 #include <stlpool.hxx>
46 #include <viewopti.hxx>
47 #include <docoptio.hxx>
48 #include <scextopt.hxx>
49 #include <unonames.hxx>
50 #include <paramisc.hxx>
51 #include <colrowst.hxx>
52 #include <otlnbuff.hxx>
53 #include <xistyle.hxx>
55 #include <namebuff.hxx>
56 #include <xltools.hxx>
57 #include <xltable.hxx>
58 #include <xltracer.hxx>
59 #include <xihelper.hxx>
60 #include <xipage.hxx>
61 #include <xiview.hxx>
62 #include <xiescher.hxx>
63 #include <xicontent.hxx>
65 #include <excform.hxx>
66 #include <documentimport.hxx>
68 #if defined(_WIN32)
69 #include <math.h>
70 #endif
72 using namespace ::com::sun::star;
74 ImportTyp::ImportTyp(ScDocument& rDoc, rtl_TextEncoding eQ)
75 : eQuellChar(eQ)
76 , rD(rDoc)
81 ImportTyp::~ImportTyp()
85 ImportExcel::ImportExcel( XclImpRootData& rImpData, SvStream& rStrm ):
86 ImportTyp( rImpData.mrDoc, rImpData.meTextEnc ),
87 XclImpRoot( rImpData ),
88 maStrm( rStrm, GetRoot() ),
89 aIn( maStrm ),
90 maScOleSize( ScAddress::INITIALIZE_INVALID ),
91 pColOutlineBuff(nullptr),
92 pRowOutlineBuff(nullptr),
93 pColRowBuff(nullptr),
94 mpLastFormula(nullptr),
95 mnLastRefIdx( 0 ),
96 mnIxfeIndex( 0 ),
97 mnLastRecId(0),
98 mbBiff2HasXfs(false),
99 mbBiff2HasXfsValid(false),
100 mbFuzzing(comphelper::IsFuzzing())
102 nBdshtTab = 0;
104 // fill in root data - after new's without root as parameter
105 pExcRoot = &GetOldRoot();
106 pExcRoot->pIR = this; // ExcRoot -> XclImpRoot
107 pExcRoot->eDateiTyp = BiffX;
108 pExcRoot->pExtSheetBuff.reset( new ExtSheetBuffer( pExcRoot ) ); //&aExtSheetBuff;
109 pExcRoot->pShrfmlaBuff.reset( new SharedFormulaBuffer( pExcRoot ) ); //&aShrfrmlaBuff;
110 pExcRoot->pExtNameBuff.reset( new ExtNameBuff ( *this ) );
112 pOutlineListBuffer.reset(new XclImpOutlineListBuffer);
114 // from Biff8 on
115 pFormConv.reset(new ExcelToSc( GetRoot() ));
116 pExcRoot->pFmlaConverter = pFormConv.get();
118 bTabTruncated = false;
120 // Excel document per Default on 31.12.1899, accords to Excel settings with 1.1.1900
121 ScDocOptions aOpt = rD.GetDocOptions();
122 aOpt.SetDate( 30, 12, 1899 );
123 rD.SetDocOptions( aOpt );
124 rD.GetFormatTable()->ChangeNullDate( 30, 12, 1899 );
126 ScDocOptions aDocOpt( rD.GetDocOptions() );
127 aDocOpt.SetIgnoreCase( true ); // always in Excel
128 aDocOpt.SetFormulaRegexEnabled( false ); // regular expressions? what's that?
129 aDocOpt.SetFormulaWildcardsEnabled( true ); // Excel uses wildcard expressions
130 aDocOpt.SetLookUpColRowNames( false ); // default: no natural language refs
131 rD.SetDocOptions( aDocOpt );
134 ImportExcel::~ImportExcel()
136 GetDoc().SetSrcCharSet( GetTextEncoding() );
138 pOutlineListBuffer.reset();
140 pFormConv.reset();
143 void ImportExcel::SetLastFormula( SCCOL nCol, SCROW nRow, double fVal, sal_uInt16 nXF, ScFormulaCell* pCell )
145 LastFormulaMapType::iterator it = maLastFormulaCells.find(nCol);
146 if (it == maLastFormulaCells.end())
148 std::pair<LastFormulaMapType::iterator, bool> r =
149 maLastFormulaCells.emplace(nCol, LastFormula());
150 it = r.first;
153 it->second.mnCol = nCol;
154 it->second.mnRow = nRow;
155 it->second.mpCell = pCell;
156 it->second.mfValue = fVal;
157 it->second.mnXF = nXF;
159 mpLastFormula = &it->second;
162 void ImportExcel::ReadFileSharing()
164 sal_uInt16 nRecommendReadOnly, nPasswordHash;
165 nRecommendReadOnly = maStrm.ReaduInt16();
166 nPasswordHash = maStrm.ReaduInt16();
168 if((nRecommendReadOnly == 0) && (nPasswordHash == 0))
169 return;
171 GetMedium().GetItemSet().Put( SfxBoolItem( SID_DOC_READONLY, true ) );
173 if( ScDocShell* pShell = GetDocShell() )
175 if( nRecommendReadOnly != 0 )
176 pShell->SetLoadReadonly( true );
177 if( nPasswordHash != 0 )
178 pShell->SetModifyPasswordHash( nPasswordHash );
182 sal_uInt16 ImportExcel::ReadXFIndex( const ScAddress& rScPos, bool bBiff2 )
184 sal_uInt16 nXFIdx = 0;
185 if( bBiff2 )
187 /* #i71453# On first call, check if the file contains XF records (by
188 trying to access the first XF with index 0). If there are no XFs,
189 the explicit formatting information contained in each cell record
190 will be used instead. */
191 if( !mbBiff2HasXfsValid )
193 mbBiff2HasXfsValid = true;
194 mbBiff2HasXfs = GetXFBuffer().GetXF( 0 ) != nullptr;
196 // read formatting information (includes the XF identifier)
197 sal_uInt8 nFlags1, nFlags2, nFlags3;
198 nFlags1 = maStrm.ReaduInt8();
199 nFlags2 = maStrm.ReaduInt8();
200 nFlags3 = maStrm.ReaduInt8();
201 /* If the file contains XFs, extract and set the XF identifier,
202 otherwise get the explicit formatting. */
203 if( mbBiff2HasXfs )
205 nXFIdx = ::extract_value< sal_uInt16 >( nFlags1, 0, 6 );
206 /* If the identifier is equal to 63, then the real identifier is
207 contained in the preceding IXFE record (stored in mnBiff2XfId). */
208 if( nXFIdx == 63 )
209 nXFIdx = mnIxfeIndex;
211 else
213 /* Let the XclImpXF class do the conversion of the imported
214 formatting. The XF buffer is empty, therefore will not do any
215 conversion based on the XF index later on. */
216 XclImpXF::ApplyPatternForBiff2CellFormat( GetRoot(), rScPos, nFlags1, nFlags2, nFlags3 );
219 else
220 nXFIdx = aIn.ReaduInt16();
221 return nXFIdx;
224 void ImportExcel::ReadDimensions()
226 XclRange aXclUsedArea;
227 if( (maStrm.GetRecId() == EXC_ID2_DIMENSIONS) || (GetBiff() <= EXC_BIFF5) )
229 maStrm >> aXclUsedArea;
230 if( (aXclUsedArea.GetColCount() > 1) && (aXclUsedArea.GetRowCount() > 1) )
232 // Excel stores first unused row/column index
233 --aXclUsedArea.maLast.mnCol;
234 --aXclUsedArea.maLast.mnRow;
235 // create the Calc range
236 SCTAB nScTab = GetCurrScTab();
237 ScRange& rScUsedArea = GetExtDocOptions().GetOrCreateTabSettings( nScTab ).maUsedArea;
238 GetAddressConverter().ConvertRange( rScUsedArea, aXclUsedArea, nScTab, nScTab, false );
239 // if any error occurs in ConvertRange(), rScUsedArea keeps untouched
242 else
244 sal_uInt32 nXclRow1 = maStrm.ReaduInt32();
245 sal_uInt32 nXclRow2 = maStrm.ReaduInt32();
246 aXclUsedArea.maFirst.mnCol = maStrm.ReaduInt16();
247 aXclUsedArea.maLast.mnCol = maStrm.ReaduInt16();
248 if( nXclRow2 != 0 && (nXclRow1 < nXclRow2) && (aXclUsedArea.GetColCount() > 1) &&
249 (nXclRow1 <= o3tl::make_unsigned( GetScMaxPos().Row() )) )
251 // Excel stores first unused row/column index
252 --nXclRow2;
253 aXclUsedArea.maLast.mnCol = o3tl::sanitizing_dec(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 ) )
321 return;
323 /* Record ID BIFF XF type String type
324 0x0004 2-7 3 byte 8-bit length, byte string
325 0x0004 8 3 byte 16-bit length, unicode string
326 0x0204 2-7 2 byte 16-bit length, byte string
327 0x0204 8 2 byte 16-bit length, unicode string */
328 bool bBiff2 = maStrm.GetRecId() == EXC_ID2_LABEL;
329 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, bBiff2 );
330 XclStrFlags nFlags = (bBiff2 && (GetBiff() <= EXC_BIFF5)) ? XclStrFlags::EightBitLength : XclStrFlags::NONE;
331 XclImpString aString;
333 // #i63105# use text encoding from FONT record
334 rtl_TextEncoding eOldTextEnc = GetTextEncoding();
335 if( const XclImpFont* pFont = GetXFBuffer().GetFont( nXFIdx ) )
336 SetTextEncoding( pFont->GetFontEncoding() );
337 aString.Read( maStrm, nFlags );
338 SetTextEncoding( eOldTextEnc );
340 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
341 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 ) )
351 return;
353 sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BOOLERR );
354 sal_uInt8 nValue, nType;
355 nValue = maStrm.ReaduInt8();
356 nType = maStrm.ReaduInt8();
358 if( nType == EXC_BOOLERR_BOOL )
359 GetXFRangeBuffer().SetBoolXF( aScPos, nXFIdx );
360 else
361 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
363 double fValue;
364 std::unique_ptr<ScTokenArray> pScTokArr = ErrorToFormula( nType != EXC_BOOLERR_BOOL, nValue, fValue );
365 ScFormulaCell* pCell = pScTokArr
366 ? new ScFormulaCell(rD, aScPos, std::move(pScTokArr))
367 : new ScFormulaCell(rD, aScPos);
368 pCell->SetHybridDouble( fValue );
369 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( !GetRoot().GetDoc().ValidRow( nRow ) )
402 return;
404 nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
405 aIn.Ignore( 2 );
407 if( GetBiff() == EXC_BIFF2 )
408 {// -------------------- BIFF2
409 pColRowBuff->SetHeight( nRow, nRowHeight );
411 else
412 {// -------------------- BIFF5
413 sal_uInt16 nGrbit;
415 aIn.Ignore( 2 ); // reserved
416 nGrbit = aIn.ReaduInt16();
418 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
419 pRowOutlineBuff->SetLevel( nRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
420 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 = aIn.ReaduInt16();
474 sal_uInt16 nColMac = aIn.ReaduInt16();
476 OSL_ENSURE( aIn.GetRecLeft() == static_cast<std::size_t>(nColMac - nColMic) * 3 + 2,
477 "ImportExcel::Columndefault - wrong record size" );
479 if (nColMac == 0)
481 SAL_WARN("sc", "dodgy column defaults");
482 return;
485 assert(nColMac > 0 && "coverity 2023.12.2");
487 nColMac--;
489 if( nColMac > rD.MaxCol() )
490 nColMac = static_cast<sal_uInt16>(rD.MaxCol());
492 for( sal_uInt16 nCol = nColMic ; nCol <= nColMac ; nCol++ )
494 sal_uInt8 nOpt0 = aIn.ReaduInt8();
495 aIn.Ignore( 2 ); // only 0. Attribute-Byte used
497 if( nOpt0 & 0x80 ) // Col hidden?
498 pColRowBuff->HideCol( nCol );
502 void ImportExcel::Array25()
504 sal_uInt16 nFormLen;
505 sal_uInt16 nFirstRow = aIn.ReaduInt16();
506 sal_uInt16 nLastRow = aIn.ReaduInt16();
507 sal_uInt8 nFirstCol = aIn.ReaduInt8();
508 sal_uInt8 nLastCol = aIn.ReaduInt8();
510 if( GetBiff() == EXC_BIFF2 )
511 {// BIFF2
512 aIn.Ignore( 1 );
513 nFormLen = aIn.ReaduInt8();
515 else
516 {// BIFF5
517 aIn.Ignore( 6 );
518 nFormLen = aIn.ReaduInt16();
521 std::unique_ptr<ScTokenArray> pResult;
523 if (GetRoot().GetDoc().ValidColRow(nLastCol, nLastRow))
525 // the read mark is now on the formula, length in nFormLen
527 pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
528 static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
529 pFormConv->Convert(pResult, maStrm, nFormLen, true);
531 SAL_WARN_IF(!pResult, "sc", "*ImportExcel::Array25(): ScTokenArray is NULL!");
534 if (pResult)
536 ScDocumentImport& rDoc = GetDocImport();
537 ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
538 rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
542 void ImportExcel::Rec1904()
544 sal_uInt16 n1904;
546 n1904 = aIn.ReaduInt16();
548 if( n1904 )
549 {// 1904 date system
550 ScDocOptions aOpt = rD.GetDocOptions();
551 aOpt.SetDate( 1, 1, 1904 );
552 rD.SetDocOptions( aOpt );
553 rD.GetFormatTable()->ChangeNullDate( 1, 1, 1904 );
557 void ImportExcel::Externname25()
559 sal_uInt32 nRes;
560 sal_uInt16 nOpt;
562 nOpt = aIn.ReaduInt16();
563 nRes = aIn.ReaduInt32();
565 aIn.ReadByteString( false ); // name
567 if( ( nOpt & 0x0001 ) || ( ( nOpt & 0xFFFE ) == 0x0000 ) )
568 {// external name
569 pExcRoot->pExtNameBuff->AddName( mnLastRefIdx );
571 else if( nOpt & 0x0010 )
572 {// ole link
573 pExcRoot->pExtNameBuff->AddOLE( mnLastRefIdx, nRes ); // nRes is storage ID
575 else
576 {// dde link
577 pExcRoot->pExtNameBuff->AddDDE( mnLastRefIdx );
581 void ImportExcel::Colwidth()
582 {// Column Width
583 sal_uInt8 nColFirst, nColLast;
584 sal_uInt16 nColWidth;
586 nColFirst = aIn.ReaduInt8();
587 nColLast = aIn.ReaduInt8();
588 nColWidth = aIn.ReaduInt16();
590 //TODO: add a check for the unlikely case of changed MAXCOL (-> XclImpAddressConverter)
591 // if( nColLast > rD.MaxCol() )
592 // nColLast = static_cast<sal_uInt16>(rD.MaxCol());
594 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
595 pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
598 void ImportExcel::Defrowheight2()
600 sal_uInt16 nDefHeight;
601 nDefHeight = maStrm.ReaduInt16();
602 nDefHeight &= 0x7FFF;
603 pColRowBuff->SetDefHeight( nDefHeight, EXC_DEFROW_UNSYNCED );
606 void ImportExcel::SheetProtect()
608 if (GetRoot().GetBiff() != EXC_BIFF8)
609 return;
611 GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
614 void ImportExcel::DocProtect()
616 if (GetRoot().GetBiff() != EXC_BIFF8)
617 return;
619 GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
622 void ImportExcel::DocPassword()
624 if (GetRoot().GetBiff() != EXC_BIFF8)
625 return;
627 GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
630 void ImportExcel::Codepage()
632 SetCodePage( maStrm.ReaduInt16() );
635 void ImportExcel::Ixfe()
637 mnIxfeIndex = maStrm.ReaduInt16();
640 void ImportExcel::DefColWidth()
642 // stored as entire characters -> convert to 1/256 of characters (as in COLINFO)
643 double fDefWidth = 256.0 * maStrm.ReaduInt16();
645 if (!pColRowBuff)
647 SAL_WARN("sc", "*ImportExcel::DefColWidth(): pColRowBuff is NULL!");
648 return;
651 // #i3006# additional space for default width - Excel adds space depending on font size
652 tools::Long nFontHt = GetFontBuffer().GetAppFontData().mnHeight;
653 fDefWidth += XclTools::GetXclDefColWidthCorrection( nFontHt );
655 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( limit_cast< sal_uInt16 >( fDefWidth ), GetCharWidth() );
656 pColRowBuff->SetDefWidth( nScWidth );
659 void ImportExcel::Colinfo()
660 {// Column Formatting Information
661 sal_uInt16 nColFirst, nColLast, nColWidth, nXF;
662 sal_uInt16 nOpt;
664 nColFirst = aIn.ReaduInt16();
665 nColLast = aIn.ReaduInt16();
666 nColWidth = aIn.ReaduInt16();
667 nXF = aIn.ReaduInt16();
668 nOpt = aIn.ReaduInt16();
670 if( nColFirst > rD.MaxCol() )
671 return;
673 if( nColLast > rD.MaxCol() )
674 nColLast = static_cast<sal_uInt16>(rD.MaxCol());
676 bool bHidden = ::get_flag( nOpt, EXC_COLINFO_HIDDEN );
677 bool bCollapsed = ::get_flag( nOpt, EXC_COLINFO_COLLAPSED );
678 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nOpt, 8, 3 );
679 pColOutlineBuff->SetLevelRange( nColFirst, nColLast, nLevel, bCollapsed );
681 if( bHidden )
682 pColRowBuff->HideColRange( nColFirst, nColLast );
684 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
685 pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
686 pColRowBuff->SetDefaultXF( nColFirst, nColLast, nXF );
689 void ImportExcel::Wsbool()
691 sal_uInt16 nFlags;
692 nFlags = aIn.ReaduInt16();
694 pRowOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_ROWBELOW ) );
695 pColOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_COLBELOW ) );
697 GetPageSettings().SetFitToPages( ::get_flag( nFlags, EXC_WSBOOL_FITTOPAGE ) );
700 void ImportExcel::Boundsheet()
702 sal_uInt16 nGrbit = 0;
704 if( GetBiff() == EXC_BIFF5 )
706 aIn.DisableDecryption();
707 maSheetOffsets.push_back( aIn.ReaduInt32() );
708 aIn.EnableDecryption();
709 nGrbit = aIn.ReaduInt16();
712 OUString aName( aIn.ReadByteString( false ) );
714 SCTAB nScTab = nBdshtTab;
715 if( nScTab > 0 )
717 OSL_ENSURE( !rD.HasTable( nScTab ), "ImportExcel::Boundsheet - sheet exists already" );
718 rD.MakeTable( nScTab );
721 if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
722 rD.SetVisible( nScTab, false );
724 if( !rD.RenameTab( nScTab, aName ) )
726 rD.CreateValidTabName( aName );
727 rD.RenameTab( nScTab, aName );
730 nBdshtTab++;
733 void ImportExcel::Country()
735 sal_uInt16 nUICountry, nDocCountry;
736 nUICountry = maStrm.ReaduInt16();
737 nDocCountry = maStrm.ReaduInt16();
739 // Store system language in XclRoot
740 LanguageType eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nDocCountry ) );
741 if( eLanguage != LANGUAGE_DONTKNOW )
742 SetDocLanguage( eLanguage );
744 // Set Excel UI language in add-in name translator
745 eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nUICountry ) );
746 if( eLanguage != LANGUAGE_DONTKNOW )
747 SetUILanguage( eLanguage );
750 void ImportExcel::ReadUsesElfs()
752 if( maStrm.ReaduInt16() != 0 )
754 ScDocOptions aDocOpt = GetDoc().GetDocOptions();
755 aDocOpt.SetLookUpColRowNames( true );
756 GetDoc().SetDocOptions( aDocOpt );
760 void ImportExcel::Hideobj()
762 sal_uInt16 nHide;
763 ScVObjMode eOle, eChart, eDraw;
765 nHide = aIn.ReaduInt16();
767 ScViewOptions aOpts( rD.GetViewOptions() );
769 switch( nHide )
771 case 1: // Placeholders
772 eOle = VOBJ_MODE_SHOW; // in Excel 97 only charts as place holder are displayed
773 eChart = VOBJ_MODE_SHOW; //#i80528# VOBJ_MODE_DUMMY replaced by VOBJ_MODE_SHOW now
774 eDraw = VOBJ_MODE_SHOW;
775 break;
776 case 2: // Hide all
777 eOle = VOBJ_MODE_HIDE;
778 eChart = VOBJ_MODE_HIDE;
779 eDraw = VOBJ_MODE_HIDE;
780 break;
781 default: // Show all
782 eOle = VOBJ_MODE_SHOW;
783 eChart = VOBJ_MODE_SHOW;
784 eDraw = VOBJ_MODE_SHOW;
785 break;
788 aOpts.SetObjMode( VOBJ_TYPE_OLE, eOle );
789 aOpts.SetObjMode( VOBJ_TYPE_CHART, eChart );
790 aOpts.SetObjMode( VOBJ_TYPE_DRAW, eDraw );
792 rD.SetViewOptions( aOpts );
795 void ImportExcel::Standardwidth()
797 sal_uInt16 nScWidth = XclTools::GetScColumnWidth( maStrm.ReaduInt16(), GetCharWidth() );
798 if (!pColRowBuff)
800 SAL_WARN("sc", "*ImportExcel::Standardwidth(): pColRowBuff is NULL!");
801 return;
803 pColRowBuff->SetDefWidth( nScWidth, true );
806 void ImportExcel::Shrfmla()
808 switch (mnLastRecId)
810 case EXC_ID2_FORMULA:
811 case EXC_ID3_FORMULA:
812 case EXC_ID4_FORMULA:
813 // This record MUST immediately follow a FORMULA record.
814 break;
815 default:
816 return;
819 if (!mpLastFormula)
820 // The last FORMULA record should have left this data.
821 return;
823 aIn.Ignore( 8 );
824 sal_uInt16 nLenExpr = aIn.ReaduInt16();
826 // read mark is now on the formula
828 std::unique_ptr<ScTokenArray> pResult;
830 // The shared range in this record is erroneous more than half the time.
831 // Don't ever rely on it. Use the one from the formula cell above.
832 SCCOL nCol1 = mpLastFormula->mnCol;
833 SCROW nRow1 = mpLastFormula->mnRow;
835 ScAddress aPos(nCol1, nRow1, GetCurrScTab());
836 pFormConv->Reset(aPos);
837 pFormConv->Convert( pResult, maStrm, nLenExpr, true, FT_SharedFormula );
839 if (!pResult)
841 SAL_WARN("sc", "+ImportExcel::Shrfmla(): ScTokenArray is NULL!");
842 return;
845 pExcRoot->pShrfmlaBuff->Store(aPos, *pResult);
847 // Create formula cell for the last formula record.
849 ScDocumentImport& rDoc = GetDocImport();
851 ScFormulaCell* pCell = new ScFormulaCell(rD, aPos, std::move(pResult));
852 pCell->GetCode()->WrapReference(aPos, EXC_MAXCOL8, EXC_MAXROW8);
853 rDoc.getDoc().CheckLinkFormulaNeedingCheck( *pCell->GetCode());
854 rDoc.getDoc().EnsureTable(aPos.Tab());
855 rDoc.setFormulaCell(aPos, pCell);
856 pCell->SetNeedNumberFormat(false);
857 if (std::isfinite(mpLastFormula->mfValue))
858 pCell->SetResultDouble(mpLastFormula->mfValue);
860 GetXFRangeBuffer().SetXF(aPos, mpLastFormula->mnXF);
861 mpLastFormula->mpCell = pCell;
864 void ImportExcel::Mulrk()
866 /* rw (2 bytes): An Rw structure that specifies the row containing the
867 cells with numeric data.
869 colFirst (2 bytes): A Col structure that specifies the first column in
870 the series of numeric cells within the sheet. The value of colFirst.col
871 MUST be less than or equal to 254.
873 rgrkrec (variable): An array of RkRec structures. Each element in the
874 array specifies an RkRec in the row. The number of entries in the array
875 MUST be equal to the value given by the following formula:
877 Number of entries in rgrkrec = (colLast.col – colFirst.col +1)
879 colLast (2 bytes): A Col structure that specifies the last column in
880 the set of numeric cells within the sheet. This colLast.col value MUST
881 be greater than the colFirst.col value. */
883 XclAddress aXclPos;
884 aIn >> aXclPos;
886 XclAddress aCurrXclPos(aXclPos);
887 while (true)
889 if (aXclPos.mnCol > aCurrXclPos.mnCol)
890 break;
891 if (aIn.GetRecLeft() <= 2)
892 break;
894 sal_uInt16 nXF = aIn.ReaduInt16();
895 sal_Int32 nRkNum = aIn.ReadInt32();
897 ScAddress aScPos( ScAddress::UNINITIALIZED );
898 if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
900 GetXFRangeBuffer().SetXF( aScPos, nXF );
901 GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRkNum));
903 ++aCurrXclPos.mnCol;
907 void ImportExcel::Mulblank()
909 /* rw (2 bytes): An Rw structure that specifies a row containing the blank
910 cells.
912 colFirst (2 bytes): A Col structure that specifies the first column in
913 the series of blank cells within the sheet. The value of colFirst.col
914 MUST be less than or equal to 254.
916 rgixfe (variable): An array of IXFCell structures. Each element of this
917 array contains an IXFCell structure corresponding to a blank cell in the
918 series. The number of entries in the array MUST be equal to the value
919 given by the following formula:
921 Number of entries in rgixfe = (colLast.col – colFirst.col +1)
923 colLast (2 bytes): A Col structure that specifies the last column in
924 the series of blank cells within the sheet. This colLast.col value MUST
925 be greater than colFirst.col value. */
927 XclAddress aXclPos;
928 aIn >> aXclPos;
930 XclAddress aCurrXclPos(aXclPos);
931 while (true)
933 if (aXclPos.mnCol > aCurrXclPos.mnCol)
934 break;
935 if (aIn.GetRecLeft() <= 2)
936 break;
938 sal_uInt16 nXF = aIn.ReaduInt16();
940 ScAddress aScPos( ScAddress::UNINITIALIZED );
941 if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
942 GetXFRangeBuffer().SetBlankXF( aScPos, nXF );
943 ++aCurrXclPos.mnCol;
947 void ImportExcel::Rstring()
949 XclAddress aXclPos;
950 sal_uInt16 nXFIdx;
951 aIn >> aXclPos;
952 nXFIdx = aIn.ReaduInt16();
954 ScAddress aScPos( ScAddress::UNINITIALIZED );
955 if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
956 return;
958 // unformatted Unicode string with separate formatting information
959 XclImpString aString;
960 aString.Read( maStrm );
962 // character formatting runs
963 if( !aString.IsRich() )
964 aString.ReadFormats( maStrm );
966 GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
967 XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, aString, nXFIdx);
970 void ImportExcel::Cellmerging()
972 XclImpAddressConverter& rAddrConv = GetAddressConverter();
973 SCTAB nScTab = GetCurrScTab();
975 sal_uInt16 nCount = maStrm.ReaduInt16();
976 sal_uInt16 nIdx = 0;
977 while (true)
979 if (maStrm.GetRecLeft() < 8)
980 break;
981 if (nIdx >= nCount)
982 break;
983 XclRange aXclRange;
984 maStrm >> aXclRange; // 16-bit rows and columns
985 ScRange aScRange( ScAddress::UNINITIALIZED );
986 if( rAddrConv.ConvertRange( aScRange, aXclRange, nScTab, nScTab, true ) )
988 const bool bTooSlowForFuzzing = mbFuzzing && (aScRange.aEnd.Col() > 512 || aScRange.aEnd.Row() > 512);
989 if (!bTooSlowForFuzzing)
990 GetXFRangeBuffer().SetMerge( aScRange.aStart.Col(), aScRange.aStart.Row(), aScRange.aEnd.Col(), aScRange.aEnd.Row() );
992 ++nIdx;
996 void ImportExcel::Olesize()
998 XclRange aXclOleSize( ScAddress::UNINITIALIZED );
999 maStrm.Ignore( 2 );
1000 aXclOleSize.Read( maStrm, false );
1002 SCTAB nScTab = GetCurrScTab();
1003 GetAddressConverter().ConvertRange( maScOleSize, aXclOleSize, nScTab, nScTab, false );
1006 void ImportExcel::Row34()
1008 sal_uInt16 nRow, nRowHeight, nGrbit, nXF;
1010 nRow = aIn.ReaduInt16();
1011 aIn.Ignore( 4 );
1013 SCROW nScRow = static_cast< SCROW >( nRow );
1015 if( !GetRoot().GetDoc().ValidRow( nScRow ) )
1016 return;
1018 nRowHeight = aIn.ReaduInt16(); // specify direct in Twips
1019 aIn.Ignore( 4 );
1021 nRowHeight = nRowHeight & 0x7FFF; // Bit 15: Row Height not changed manually
1022 if( !nRowHeight )
1023 nRowHeight = (GetBiff() == EXC_BIFF2) ? 0x25 : 0x225;
1025 nGrbit = aIn.ReaduInt16();
1026 nXF = aIn.ReaduInt16();
1028 sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
1029 pRowOutlineBuff->SetLevel( nScRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
1030 pColRowBuff->SetRowSettings( nScRow, nRowHeight, nGrbit );
1032 if( nGrbit & EXC_ROW_USEDEFXF )
1033 GetXFRangeBuffer().SetRowDefXF( nScRow, nXF & EXC_ROW_XFMASK );
1036 void ImportExcel::Bof3()
1038 sal_uInt16 nSubType;
1039 maStrm.DisableDecryption();
1040 maStrm.Ignore( 2 );
1041 nSubType = maStrm.ReaduInt16();
1043 OSL_ENSURE( nSubType != 0x0100, "*ImportExcel::Bof3(): Biff3 as Workbook?!" );
1044 if( nSubType == 0x0100 ) // Book
1045 pExcRoot->eDateiTyp = Biff3W;
1046 else if( nSubType == 0x0020 ) // Chart
1047 pExcRoot->eDateiTyp = Biff3C;
1048 else if( nSubType == 0x0040 ) // Macro
1049 pExcRoot->eDateiTyp = Biff3M;
1050 else // #i51490# Excel interprets invalid indexes as worksheet
1051 pExcRoot->eDateiTyp = Biff3;
1054 void ImportExcel::Array34()
1056 sal_uInt16 nFirstRow, nLastRow, nFormLen;
1057 sal_uInt8 nFirstCol, nLastCol;
1059 nFirstRow = aIn.ReaduInt16();
1060 nLastRow = aIn.ReaduInt16();
1061 nFirstCol = aIn.ReaduInt8();
1062 nLastCol = aIn.ReaduInt8();
1063 aIn.Ignore( (GetBiff() >= EXC_BIFF5) ? 6 : 2 );
1064 nFormLen = aIn.ReaduInt16();
1066 std::unique_ptr<ScTokenArray> pResult;
1068 if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
1070 // the read mark is now on the formula, length in nFormLen
1072 pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
1073 static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
1074 pFormConv->Convert( pResult, maStrm, nFormLen, true );
1076 SAL_WARN_IF(!pResult, "sc", "+ImportExcel::Array34(): ScTokenArray is NULL!");
1079 if (pResult)
1081 ScDocumentImport& rDoc = GetDocImport();
1082 ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
1083 rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
1087 void ImportExcel::Defrowheight345()
1089 sal_uInt16 nFlags, nDefHeight;
1090 nFlags = maStrm.ReaduInt16();
1091 nDefHeight = maStrm.ReaduInt16();
1093 if (!pColRowBuff)
1095 SAL_WARN("sc", "*ImportExcel::Defrowheight345(): pColRowBuff is NULL!");
1096 return;
1099 pColRowBuff->SetDefHeight( nDefHeight, nFlags );
1102 void ImportExcel::TableOp()
1104 sal_uInt16 nFirstRow = aIn.ReaduInt16();
1105 sal_uInt16 nLastRow = aIn.ReaduInt16();
1106 sal_uInt8 nFirstCol = aIn.ReaduInt8();
1107 sal_uInt8 nLastCol = aIn.ReaduInt8();
1108 sal_uInt16 nGrbit = aIn.ReaduInt16();
1109 sal_uInt16 nInpRow = aIn.ReaduInt16();
1110 sal_uInt16 nInpCol = aIn.ReaduInt16();
1111 sal_uInt16 nInpRow2 = aIn.ReaduInt16();
1112 sal_uInt16 nInpCol2 = aIn.ReaduInt16();
1114 if (mbFuzzing)
1116 //shrink to smallish arbitrary value to not timeout
1117 nLastRow = std::min<sal_uInt16>(nLastRow, MAXROW_30 / 2);
1120 if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
1122 if( nFirstCol && nFirstRow )
1124 ScTabOpParam aTabOpParam;
1125 aTabOpParam.meMode = (nGrbit & EXC_TABLEOP_BOTH) ? ScTabOpParam::Both : ((nGrbit & EXC_TABLEOP_ROW) ? ScTabOpParam::Row : ScTabOpParam::Column);
1126 sal_uInt16 nCol = nFirstCol - 1;
1127 sal_uInt16 nRow = nFirstRow - 1;
1128 SCTAB nTab = GetCurrScTab();
1129 switch (aTabOpParam.meMode)
1131 case ScTabOpParam::Column:
1132 aTabOpParam.aRefFormulaCell.Set(
1133 static_cast<SCCOL>(nFirstCol),
1134 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1135 false, false );
1136 aTabOpParam.aRefFormulaEnd.Set(
1137 static_cast<SCCOL>(nLastCol),
1138 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1139 false, false );
1140 aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol),
1141 static_cast<SCROW>(nInpRow), nTab, false, false,
1142 false );
1143 nRow++;
1144 break;
1145 case ScTabOpParam::Row:
1146 aTabOpParam.aRefFormulaCell.Set(
1147 static_cast<SCCOL>(nFirstCol - 1),
1148 static_cast<SCROW>(nFirstRow), nTab, false, false,
1149 false );
1150 aTabOpParam.aRefFormulaEnd.Set(
1151 static_cast<SCCOL>(nFirstCol - 1),
1152 static_cast<SCROW>(nLastRow), nTab, false, false,
1153 false );
1154 aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1155 static_cast<SCROW>(nInpRow), nTab, false, false,
1156 false );
1157 nCol++;
1158 break;
1159 case ScTabOpParam::Both: // TWO-INPUT
1160 aTabOpParam.aRefFormulaCell.Set(
1161 static_cast<SCCOL>(nFirstCol - 1),
1162 static_cast<SCROW>(nFirstRow - 1), nTab, false,
1163 false, false );
1164 aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1165 static_cast<SCROW>(nInpRow), nTab, false, false,
1166 false );
1167 aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol2),
1168 static_cast<SCROW>(nInpRow2), nTab, false, false,
1169 false );
1170 break;
1173 ScDocumentImport& rDoc = GetDocImport();
1174 ScRange aTabOpRange(nCol, nRow, nTab, nLastCol, nLastRow, nTab);
1175 rDoc.setTableOpCells(aTabOpRange, aTabOpParam);
1178 else
1180 bTabTruncated = true;
1181 GetTracer().TraceInvalidRow(nLastRow, rD.MaxRow());
1185 void ImportExcel::Bof4()
1187 sal_uInt16 nSubType;
1188 maStrm.DisableDecryption();
1189 maStrm.Ignore( 2 );
1190 nSubType = maStrm.ReaduInt16();
1192 if( nSubType == 0x0100 ) // Book
1193 pExcRoot->eDateiTyp = Biff4W;
1194 else if( nSubType == 0x0020 ) // Chart
1195 pExcRoot->eDateiTyp = Biff4C;
1196 else if( nSubType == 0x0040 ) // Macro
1197 pExcRoot->eDateiTyp = Biff4M;
1198 else // #i51490# Excel interprets invalid indexes as worksheet
1199 pExcRoot->eDateiTyp = Biff4;
1202 void ImportExcel::Bof5()
1204 //POST: eDateiTyp = Type of the file to be read
1205 sal_uInt16 nSubType, nVers;
1206 BiffTyp eDatei;
1208 maStrm.DisableDecryption();
1209 nVers = maStrm.ReaduInt16();
1210 nSubType = maStrm.ReaduInt16( );
1212 switch( nSubType )
1214 case 0x0005: eDatei = Biff5W; break; // workbook globals
1215 case 0x0006: eDatei = Biff5V; break; // VB module
1216 case 0x0020: eDatei = Biff5C; break; // chart
1217 case 0x0040: eDatei = Biff5M4; break; // macro sheet
1218 case 0x0010: // worksheet
1219 default: eDatei = Biff5; break; // tdf#144732 Excel interprets invalid indexes as worksheet
1222 if( nVers == 0x0600 && (GetBiff() == EXC_BIFF8) )
1223 eDatei = static_cast<BiffTyp>( eDatei - Biff5 + Biff8 );
1225 pExcRoot->eDateiTyp = eDatei;
1228 void ImportExcel::EndSheet()
1230 pExcRoot->pExtSheetBuff->Reset();
1232 if( GetBiff() <= EXC_BIFF5 )
1234 pExcRoot->pExtNameBuff->Reset();
1235 mnLastRefIdx = 0;
1238 FinalizeTable();
1241 void ImportExcel::NewTable()
1243 SCTAB nTab = GetCurrScTab();
1244 if( nTab > 0 && !rD.HasTable( nTab ) )
1245 rD.MakeTable( nTab );
1247 if (nTab == 0 && GetBiff() == EXC_BIFF2)
1249 // For Excel 2.1 Worksheet file, we need to set the file name as the
1250 // sheet name.
1251 INetURLObject aURL(GetDocUrl());
1252 rD.RenameTab(0, aURL.getBase());
1255 pExcRoot->pShrfmlaBuff->Clear();
1256 maLastFormulaCells.clear();
1257 mpLastFormula = nullptr;
1259 InitializeTable( nTab );
1261 XclImpOutlineDataBuffer* pNewItem = new XclImpOutlineDataBuffer( GetRoot(), nTab );
1262 pOutlineListBuffer->push_back( std::unique_ptr<XclImpOutlineDataBuffer>(pNewItem) );
1263 pExcRoot->pColRowBuff = pColRowBuff = pNewItem->GetColRowBuff();
1264 pColOutlineBuff = pNewItem->GetColOutline();
1265 pRowOutlineBuff = pNewItem->GetRowOutline();
1268 std::unique_ptr<ScTokenArray> ImportExcel::ErrorToFormula( bool bErrOrVal, sal_uInt8 nError, double& rVal )
1270 return pFormConv->GetBoolErr( XclTools::ErrorToEnum( rVal, bErrOrVal, nError ) );
1273 void ImportExcel::AdjustRowHeight()
1275 /* Speed up chart import: import all sheets without charts, then
1276 update row heights (here), last load all charts -> do not any longer
1277 update inside of ScDocShell::ConvertFrom() (causes update of existing
1278 charts during each and every change of row height). */
1279 if( ScModelObj* pDocObj = GetDocModelObj() )
1280 pDocObj->UpdateAllRowHeights();
1283 void ImportExcel::PostDocLoad()
1285 /* Set automatic page numbering in Default page style (default is "page number = 1").
1286 Otherwise hidden tables (i.e. for scenarios) which have Default page style will
1287 break automatic page numbering. */
1288 if( SfxStyleSheetBase* pStyleSheet = GetStyleSheetPool().Find( ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Page ) )
1289 pStyleSheet->GetItemSet().Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 0 ) );
1291 // outlines for all sheets, sets hidden rows and columns (#i11776# after filtered ranges)
1292 for (auto& rxBuffer : *pOutlineListBuffer)
1293 rxBuffer->Convert();
1295 // document view settings (before visible OLE area)
1296 GetDocViewSettings().Finalize();
1298 // process all drawing objects (including OLE, charts, controls; after hiding rows/columns; before visible OLE area)
1299 GetObjectManager().ConvertObjects();
1301 // visible area (used if this document is an embedded OLE object)
1302 if( ScDocShell* pDocShell = GetDocShell() )
1304 // visible area if embedded
1305 const ScExtDocSettings& rDocSett = GetExtDocOptions().GetDocSettings();
1306 SCTAB nDisplScTab = rDocSett.mnDisplTab;
1308 /* #i44077# If a new OLE object is inserted from file, there is no
1309 OLESIZE record in the Excel file. Calculate used area from file
1310 contents (used cells and drawing objects). */
1311 if( !maScOleSize.IsValid() )
1313 // used area of displayed sheet (cell contents)
1314 if( const ScExtTabSettings* pTabSett = GetExtDocOptions().GetTabSettings( nDisplScTab ) )
1315 maScOleSize = pTabSett->maUsedArea;
1316 // add all valid drawing objects
1317 ScRange aScObjArea = GetObjectManager().GetUsedArea( nDisplScTab );
1318 if( aScObjArea.IsValid() )
1319 maScOleSize.ExtendTo( aScObjArea );
1322 // valid size found - set it at the document
1323 if( maScOleSize.IsValid() )
1325 pDocShell->SetVisArea( GetDoc().GetMMRect(
1326 maScOleSize.aStart.Col(), maScOleSize.aStart.Row(),
1327 maScOleSize.aEnd.Col(), maScOleSize.aEnd.Row(), nDisplScTab ) );
1328 GetDoc().SetVisibleTab( nDisplScTab );
1332 // open forms in alive mode (has no effect, if no controls in document)
1333 if( ScModelObj* pDocObj = GetDocModelObj() )
1334 pDocObj->setPropertyValue( SC_UNO_APPLYFMDES, uno::Any( false ) );
1336 // enables extended options to be set to the view after import
1337 GetExtDocOptions().SetChanged( true );
1339 // root data owns the extended document options -> create a new object
1340 GetDoc().SetExtDocOptions( std::make_unique<ScExtDocOptions>( GetExtDocOptions() ) );
1342 const SCTAB nLast = rD.GetTableCount();
1343 const ScRange* p;
1345 if( GetRoot().GetPrintAreaBuffer().HasRanges() )
1347 for( SCTAB n = 0 ; n < nLast ; n++ )
1349 p = GetRoot().GetPrintAreaBuffer().First(n);
1350 if( p )
1352 rD.ClearPrintRanges( n );
1353 while( p )
1355 rD.AddPrintRange( n, *p );
1356 p = GetRoot().GetPrintAreaBuffer().Next();
1359 else
1361 // #i4063# no print ranges -> print entire sheet
1362 rD.SetPrintEntireSheet( n );
1365 GetTracer().TracePrintRange();
1368 if( !GetRoot().GetTitleAreaBuffer().HasRanges() )
1369 return;
1371 for( SCTAB n = 0 ; n < nLast ; n++ )
1373 p = GetRoot().GetTitleAreaBuffer().First(n);
1374 if( p )
1376 bool bRowVirgin = true;
1377 bool bColVirgin = true;
1379 while( p )
1381 if( p->aStart.Col() == 0 && p->aEnd.Col() == rD.MaxCol() && bRowVirgin )
1383 rD.SetRepeatRowRange( n, *p );
1384 bRowVirgin = false;
1387 if( p->aStart.Row() == 0 && p->aEnd.Row() == rD.MaxRow() && bColVirgin )
1389 rD.SetRepeatColRange( n, *p );
1390 bColVirgin = false;
1393 p = GetRoot().GetTitleAreaBuffer().Next();
1399 XclImpOutlineDataBuffer::XclImpOutlineDataBuffer( const XclImpRoot& rRoot, SCTAB nScTab ) :
1400 XclImpRoot( rRoot ),
1401 mxColOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Col() + 1 ) ),
1402 mxRowOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Row() + 1 ) ),
1403 mxColRowBuff( std::make_shared<XclImpColRowSettings>( rRoot ) ),
1404 mnScTab( nScTab )
1408 XclImpOutlineDataBuffer::~XclImpOutlineDataBuffer()
1412 void XclImpOutlineDataBuffer::Convert()
1414 mxColOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetColArray() );
1415 mxColOutlineBuff->MakeScOutline();
1417 mxRowOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetRowArray() );
1418 mxRowOutlineBuff->MakeScOutline();
1420 mxColRowBuff->ConvertHiddenFlags( mnScTab );
1423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */