1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <memory>
21 #include <imp_op.hxx>
22 
23 #include <filter/msfilter/countryid.hxx>
24 
25 #include <scitems.hxx>
26 
27 #include <o3tl/safeint.hxx>
28 #include <sfx2/docfile.hxx>
29 #include <svx/svxids.hrc>
30 #include <svl/zforlist.hxx>
31 #include <unotools/configmgr.hxx>
32 #include <sal/log.hxx>
33 
34 #include <sfx2/objsh.hxx>
35 #include <tools/urlobj.hxx>
36 #include <docuno.hxx>
37 
38 #include <formulacell.hxx>
39 #include <document.hxx>
40 #include <globstr.hrc>
41 #include <scresid.hxx>
42 #include <global.hxx>
43 #include <olinetab.hxx>
44 #include <stlpool.hxx>
45 #include <viewopti.hxx>
46 #include <docoptio.hxx>
47 #include <scextopt.hxx>
48 #include <unonames.hxx>
49 #include <paramisc.hxx>
50 #include <colrowst.hxx>
51 #include <otlnbuff.hxx>
52 #include <xistyle.hxx>
53 
54 #include <namebuff.hxx>
55 #include <xltools.hxx>
56 #include <xltable.hxx>
57 #include <xltracer.hxx>
58 #include <xihelper.hxx>
59 #include <xipage.hxx>
60 #include <xiview.hxx>
61 #include <xiescher.hxx>
62 #include <xicontent.hxx>
63 
64 #include <excform.hxx>
65 #include <documentimport.hxx>
66 
67 #if defined(_WIN32)
68 #include <math.h>
69 #endif
70 
71 using namespace ::com::sun::star;
72 
ImportTyp(ScDocument & rDoc,rtl_TextEncoding eQ)73 ImportTyp::ImportTyp(ScDocument& rDoc, rtl_TextEncoding eQ)
74     : eQuellChar(eQ)
75     , rD(rDoc)
76 
77 {
78 }
79 
~ImportTyp()80 ImportTyp::~ImportTyp()
81 {
82 }
83 
ImportExcel(XclImpRootData & rImpData,SvStream & rStrm)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)
99 {
100     nBdshtTab = 0;
101 
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 ) );
109 
110     pOutlineListBuffer.reset(new XclImpOutlineListBuffer);
111 
112     // from Biff8 on
113     pFormConv.reset(new ExcelToSc( GetRoot() ));
114     pExcRoot->pFmlaConverter = pFormConv.get();
115 
116     bTabTruncated = false;
117 
118     // Excel document per Default on 31.12.1899, accords to Excel settings with 1.1.1900
119     ScDocOptions aOpt = rD.GetDocOptions();
120     aOpt.SetDate( 30, 12, 1899 );
121     rD.SetDocOptions( aOpt );
122     rD.GetFormatTable()->ChangeNullDate( 30, 12, 1899 );
123 
124     ScDocOptions aDocOpt( rD.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     rD.SetDocOptions( aDocOpt );
130 }
131 
~ImportExcel()132 ImportExcel::~ImportExcel()
133 {
134     GetDoc().SetSrcCharSet( GetTextEncoding() );
135 
136     pOutlineListBuffer.reset();
137 
138     pFormConv.reset();
139 }
140 
SetLastFormula(SCCOL nCol,SCROW nRow,double fVal,sal_uInt16 nXF,ScFormulaCell * pCell)141 void ImportExcel::SetLastFormula( SCCOL nCol, SCROW nRow, double fVal, sal_uInt16 nXF, ScFormulaCell* pCell )
142 {
143     LastFormulaMapType::iterator it = maLastFormulaCells.find(nCol);
144     if (it == maLastFormulaCells.end())
145     {
146         std::pair<LastFormulaMapType::iterator, bool> r =
147             maLastFormulaCells.emplace(nCol, LastFormula());
148         it = r.first;
149     }
150 
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;
156 
157     mpLastFormula = &it->second;
158 }
159 
ReadFileSharing()160 void ImportExcel::ReadFileSharing()
161 {
162     sal_uInt16 nRecommendReadOnly, nPasswordHash;
163     nRecommendReadOnly = maStrm.ReaduInt16();
164     nPasswordHash = maStrm.ReaduInt16();
165 
166     if((nRecommendReadOnly == 0) && (nPasswordHash == 0))
167         return;
168 
169     if( SfxItemSet* pItemSet = GetMedium().GetItemSet() )
170         pItemSet->Put( SfxBoolItem( SID_DOC_READONLY, true ) );
171 
172     if( SfxObjectShell* pShell = GetDocShell() )
173     {
174         if( nRecommendReadOnly != 0 )
175             pShell->SetLoadReadonly( true );
176         if( nPasswordHash != 0 )
177             pShell->SetModifyPasswordHash( nPasswordHash );
178     }
179 }
180 
ReadXFIndex(const ScAddress & rScPos,bool bBiff2)181 sal_uInt16 ImportExcel::ReadXFIndex( const ScAddress& rScPos, bool bBiff2 )
182 {
183     sal_uInt16 nXFIdx = 0;
184     if( bBiff2 )
185     {
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 )
191         {
192             mbBiff2HasXfsValid = true;
193             mbBiff2HasXfs = GetXFBuffer().GetXF( 0 ) != nullptr;
194         }
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 )
203         {
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;
209         }
210         else
211         {
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 );
216         }
217     }
218     else
219         nXFIdx = aIn.ReaduInt16();
220     return nXFIdx;
221 }
222 
ReadDimensions()223 void ImportExcel::ReadDimensions()
224 {
225     XclRange aXclUsedArea;
226     if( (maStrm.GetRecId() == EXC_ID2_DIMENSIONS) || (GetBiff() <= EXC_BIFF5) )
227     {
228         maStrm >> aXclUsedArea;
229         if( (aXclUsedArea.GetColCount() > 1) && (aXclUsedArea.GetRowCount() > 1) )
230         {
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
239         }
240     }
241     else
242     {
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 <= o3tl::make_unsigned( GetScMaxPos().Row() )) )
250         {
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
262         }
263     }
264 }
265 
ReadBlank()266 void ImportExcel::ReadBlank()
267 {
268     XclAddress aXclPos;
269     aIn >> aXclPos;
270 
271     ScAddress aScPos( ScAddress::UNINITIALIZED );
272     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
273     {
274         sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BLANK );
275 
276         GetXFRangeBuffer().SetBlankXF( aScPos, nXFIdx );
277     }
278 }
279 
ReadInteger()280 void ImportExcel::ReadInteger()
281 {
282     XclAddress aXclPos;
283     maStrm >> aXclPos;
284 
285     ScAddress aScPos( ScAddress::UNINITIALIZED );
286     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
287     {
288         sal_uInt16 nXFIdx = ReadXFIndex( aScPos, true );
289         sal_uInt16 nValue;
290         nValue = maStrm.ReaduInt16();
291 
292         GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
293         GetDocImport().setNumericCell(aScPos, nValue);
294     }
295 }
296 
ReadNumber()297 void ImportExcel::ReadNumber()
298 {
299     XclAddress aXclPos;
300     maStrm >> aXclPos;
301 
302     ScAddress aScPos( ScAddress::UNINITIALIZED );
303     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
304     {
305         sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_NUMBER );
306         double fValue;
307         fValue = maStrm.ReadDouble();
308 
309         GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
310         GetDocImport().setNumericCell(aScPos, fValue);
311     }
312 }
313 
ReadLabel()314 void ImportExcel::ReadLabel()
315 {
316     XclAddress aXclPos;
317     maStrm >> aXclPos;
318 
319     ScAddress aScPos( ScAddress::UNINITIALIZED );
320     if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
321         return;
322 
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;
332 
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 );
339 
340     GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
341     XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, GetRoot(), aString, nXFIdx);
342 }
343 
ReadBoolErr()344 void ImportExcel::ReadBoolErr()
345 {
346     XclAddress aXclPos;
347     maStrm >> aXclPos;
348 
349     ScAddress aScPos( ScAddress::UNINITIALIZED );
350     if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
351         return;
352 
353     sal_uInt16 nXFIdx = ReadXFIndex( aScPos, maStrm.GetRecId() == EXC_ID2_BOOLERR );
354     sal_uInt8 nValue, nType;
355     nValue = maStrm.ReaduInt8();
356     nType = maStrm.ReaduInt8();
357 
358     if( nType == EXC_BOOLERR_BOOL )
359         GetXFRangeBuffer().SetBoolXF( aScPos, nXFIdx );
360     else
361         GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
362 
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);
370 }
371 
ReadRk()372 void ImportExcel::ReadRk()
373 {
374     XclAddress aXclPos;
375     maStrm >> aXclPos;
376 
377     ScAddress aScPos( ScAddress::UNINITIALIZED );
378     if( GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
379     {
380         sal_uInt16 nXFIdx = ReadXFIndex( aScPos, false );
381         sal_Int32 nRk;
382         nRk = maStrm.ReadInt32();
383 
384         GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
385         GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRk));
386     }
387 }
388 
Window1()389 void ImportExcel::Window1()
390 {
391     GetDocViewSettings().ReadWindow1( maStrm );
392 }
393 
Row25()394 void ImportExcel::Row25()
395 {
396     sal_uInt16  nRow, nRowHeight;
397 
398     nRow = aIn.ReaduInt16();
399     aIn.Ignore( 4 );
400 
401     if( !GetRoot().GetDoc().ValidRow( nRow ) )
402         return;
403 
404     nRowHeight = aIn.ReaduInt16();  // specify direct in Twips
405     aIn.Ignore( 2 );
406 
407     if( GetBiff() == EXC_BIFF2 )
408     {// -------------------- BIFF2
409         pColRowBuff->SetHeight( nRow, nRowHeight );
410     }
411     else
412     {// -------------------- BIFF5
413         sal_uInt16  nGrbit;
414 
415         aIn.Ignore( 2 );   // reserved
416         nGrbit = aIn.ReaduInt16();
417 
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 );
421     }
422 }
423 
Bof2()424 void ImportExcel::Bof2()
425 {
426     sal_uInt16 nSubType;
427     maStrm.DisableDecryption();
428     maStrm.Ignore( 2 );
429     nSubType = maStrm.ReaduInt16();
430 
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;
437 }
438 
Eof()439 void ImportExcel::Eof()
440 {
441     //  POST: cannot be called after an invalid table!
442     EndSheet();
443     IncCurrScTab();
444 }
445 
SheetPassword()446 void ImportExcel::SheetPassword()
447 {
448     if (GetRoot().GetBiff() != EXC_BIFF8)
449         return;
450 
451     GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() );
452 }
453 
Externsheet()454 void ImportExcel::Externsheet()
455 {
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 );
461 }
462 
WinProtection()463 void ImportExcel:: WinProtection()
464 {
465     if (GetRoot().GetBiff() != EXC_BIFF8)
466         return;
467 
468     GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn );
469 }
470 
Columndefault()471 void ImportExcel::Columndefault()
472 {// Default Cell Attributes
473     sal_uInt16  nColMic, nColMac;
474     sal_uInt8   nOpt0;
475 
476     nColMic = aIn.ReaduInt16();
477     nColMac = aIn.ReaduInt16();
478 
479     OSL_ENSURE( aIn.GetRecLeft() == static_cast<std::size_t>(nColMac - nColMic) * 3 + 2,
480                 "ImportExcel::Columndefault - wrong record size" );
481 
482     nColMac--;
483 
484     if( nColMac > rD.MaxCol() )
485         nColMac = static_cast<sal_uInt16>(rD.MaxCol());
486 
487     for( sal_uInt16 nCol = nColMic ; nCol <= nColMac ; nCol++ )
488     {
489         nOpt0 = aIn.ReaduInt8();
490         aIn.Ignore( 2 );   // only 0. Attribute-Byte used
491 
492         if( nOpt0 & 0x80 )  // Col hidden?
493             pColRowBuff->HideCol( nCol );
494     }
495 }
496 
Array25()497 void ImportExcel::Array25()
498 {
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();
504 
505     if( GetBiff() == EXC_BIFF2 )
506     {//                     BIFF2
507         aIn.Ignore( 1 );
508         nFormLen = aIn.ReaduInt8();
509     }
510     else
511     {//                     BIFF5
512         aIn.Ignore( 6 );
513         nFormLen = aIn.ReaduInt16();
514     }
515 
516     std::unique_ptr<ScTokenArray> pResult;
517 
518     if (GetRoot().GetDoc().ValidColRow(nLastCol, nLastRow))
519     {
520         // the read mark is now on the formula, length in nFormLen
521 
522         pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
523                     static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
524         pFormConv->Convert(pResult, maStrm, nFormLen, true);
525 
526         SAL_WARN_IF(!pResult, "sc", "*ImportExcel::Array25(): ScTokenArray is NULL!");
527     }
528 
529     if (pResult)
530     {
531         ScDocumentImport& rDoc = GetDocImport();
532         ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
533         rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
534     }
535 }
536 
Rec1904()537 void ImportExcel::Rec1904()
538 {
539     sal_uInt16  n1904;
540 
541     n1904 = aIn.ReaduInt16();
542 
543     if( n1904 )
544     {// 1904 date system
545         ScDocOptions aOpt = rD.GetDocOptions();
546         aOpt.SetDate( 1, 1, 1904 );
547         rD.SetDocOptions( aOpt );
548         rD.GetFormatTable()->ChangeNullDate( 1, 1, 1904 );
549     }
550 }
551 
Externname25()552 void ImportExcel::Externname25()
553 {
554     sal_uInt32      nRes;
555     sal_uInt16      nOpt;
556 
557     nOpt = aIn.ReaduInt16();
558     nRes = aIn.ReaduInt32();
559 
560     aIn.ReadByteString( false ); // name
561 
562     if( ( nOpt & 0x0001 ) || ( ( nOpt & 0xFFFE ) == 0x0000 ) )
563     {// external name
564         pExcRoot->pExtNameBuff->AddName( mnLastRefIdx );
565     }
566     else if( nOpt & 0x0010 )
567     {// ole link
568         pExcRoot->pExtNameBuff->AddOLE( mnLastRefIdx, nRes );        // nRes is storage ID
569     }
570     else
571     {// dde link
572         pExcRoot->pExtNameBuff->AddDDE( mnLastRefIdx );
573     }
574 }
575 
Colwidth()576 void ImportExcel::Colwidth()
577 {// Column Width
578     sal_uInt8   nColFirst, nColLast;
579     sal_uInt16  nColWidth;
580 
581     nColFirst = aIn.ReaduInt8();
582     nColLast = aIn.ReaduInt8();
583     nColWidth = aIn.ReaduInt16();
584 
585 //TODO: add a check for the unlikely case of changed MAXCOL (-> XclImpAddressConverter)
586 //   if( nColLast > rD.MaxCol() )
587 //       nColLast = static_cast<sal_uInt16>(rD.MaxCol());
588 
589     sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
590     pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
591 }
592 
Defrowheight2()593 void ImportExcel::Defrowheight2()
594 {
595     sal_uInt16 nDefHeight;
596     nDefHeight = maStrm.ReaduInt16();
597     nDefHeight &= 0x7FFF;
598     pColRowBuff->SetDefHeight( nDefHeight, EXC_DEFROW_UNSYNCED );
599 }
600 
SheetProtect()601 void ImportExcel::SheetProtect()
602 {
603     if (GetRoot().GetBiff() != EXC_BIFF8)
604         return;
605 
606     GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() );
607 }
608 
DocProtect()609 void ImportExcel::DocProtect()
610 {
611     if (GetRoot().GetBiff() != EXC_BIFF8)
612         return;
613 
614     GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn );
615 }
616 
DocPassword()617 void ImportExcel::DocPassword()
618 {
619     if (GetRoot().GetBiff() != EXC_BIFF8)
620         return;
621 
622     GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn );
623 }
624 
Codepage()625 void ImportExcel::Codepage()
626 {
627     SetCodePage( maStrm.ReaduInt16() );
628 }
629 
Ixfe()630 void ImportExcel::Ixfe()
631 {
632     mnIxfeIndex = maStrm.ReaduInt16();
633 }
634 
DefColWidth()635 void ImportExcel::DefColWidth()
636 {
637     // stored as entire characters -> convert to 1/256 of characters (as in COLINFO)
638     double fDefWidth = 256.0 * maStrm.ReaduInt16();
639 
640     if (!pColRowBuff)
641     {
642         SAL_WARN("sc", "*ImportExcel::DefColWidth(): pColRowBuff is NULL!");
643         return;
644     }
645 
646     // #i3006# additional space for default width - Excel adds space depending on font size
647     tools::Long nFontHt = GetFontBuffer().GetAppFontData().mnHeight;
648     fDefWidth += XclTools::GetXclDefColWidthCorrection( nFontHt );
649 
650     sal_uInt16 nScWidth = XclTools::GetScColumnWidth( limit_cast< sal_uInt16 >( fDefWidth ), GetCharWidth() );
651     pColRowBuff->SetDefWidth( nScWidth );
652 }
653 
Colinfo()654 void ImportExcel::Colinfo()
655 {// Column Formatting Information
656     sal_uInt16  nColFirst, nColLast, nColWidth, nXF;
657     sal_uInt16  nOpt;
658 
659     nColFirst = aIn.ReaduInt16();
660     nColLast = aIn.ReaduInt16();
661     nColWidth = aIn.ReaduInt16();
662     nXF = aIn.ReaduInt16();
663     nOpt = aIn.ReaduInt16();
664 
665     if( nColFirst > rD.MaxCol() )
666         return;
667 
668     if( nColLast > rD.MaxCol() )
669         nColLast = static_cast<sal_uInt16>(rD.MaxCol());
670 
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 );
675 
676     if( bHidden )
677         pColRowBuff->HideColRange( nColFirst, nColLast );
678 
679     sal_uInt16 nScWidth = XclTools::GetScColumnWidth( nColWidth, GetCharWidth() );
680     pColRowBuff->SetWidthRange( nColFirst, nColLast, nScWidth );
681     pColRowBuff->SetDefaultXF( nColFirst, nColLast, nXF );
682 }
683 
Wsbool()684 void ImportExcel::Wsbool()
685 {
686     sal_uInt16 nFlags;
687     nFlags = aIn.ReaduInt16();
688 
689     pRowOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_ROWBELOW ) );
690     pColOutlineBuff->SetButtonMode( ::get_flag( nFlags, EXC_WSBOOL_COLBELOW ) );
691 
692     GetPageSettings().SetFitToPages( ::get_flag( nFlags, EXC_WSBOOL_FITTOPAGE ) );
693 }
694 
Boundsheet()695 void ImportExcel::Boundsheet()
696 {
697     sal_uInt16 nGrbit = 0;
698 
699     if( GetBiff() == EXC_BIFF5 )
700     {
701         aIn.DisableDecryption();
702         maSheetOffsets.push_back( aIn.ReaduInt32() );
703         aIn.EnableDecryption();
704         nGrbit = aIn.ReaduInt16();
705     }
706 
707     OUString aName( aIn.ReadByteString( false ) );
708 
709     SCTAB nScTab = nBdshtTab;
710     if( nScTab > 0 )
711     {
712         OSL_ENSURE( !rD.HasTable( nScTab ), "ImportExcel::Boundsheet - sheet exists already" );
713         rD.MakeTable( nScTab );
714     }
715 
716     if( ( nGrbit & 0x0001 ) || ( nGrbit & 0x0002 ) )
717         rD.SetVisible( nScTab, false );
718 
719     if( !rD.RenameTab( nScTab, aName ) )
720     {
721         rD.CreateValidTabName( aName );
722         rD.RenameTab( nScTab, aName );
723     }
724 
725     nBdshtTab++;
726 }
727 
Country()728 void ImportExcel::Country()
729 {
730     sal_uInt16 nUICountry, nDocCountry;
731     nUICountry = maStrm.ReaduInt16();
732     nDocCountry = maStrm.ReaduInt16();
733 
734     // Store system language in XclRoot
735     LanguageType eLanguage = ::msfilter::ConvertCountryToLanguage( static_cast< ::msfilter::CountryId >( nDocCountry ) );
736     if( eLanguage != LANGUAGE_DONTKNOW )
737         SetDocLanguage( eLanguage );
738 
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 );
743 }
744 
ReadUsesElfs()745 void ImportExcel::ReadUsesElfs()
746 {
747     if( maStrm.ReaduInt16() != 0 )
748     {
749         ScDocOptions aDocOpt = GetDoc().GetDocOptions();
750         aDocOpt.SetLookUpColRowNames( true );
751         GetDoc().SetDocOptions( aDocOpt );
752     }
753 }
754 
Hideobj()755 void ImportExcel::Hideobj()
756 {
757     sal_uInt16      nHide;
758     ScVObjMode  eOle, eChart, eDraw;
759 
760     nHide = aIn.ReaduInt16();
761 
762     ScViewOptions aOpts( rD.GetViewOptions() );
763 
764     switch( nHide )
765     {
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;
781     }
782 
783     aOpts.SetObjMode( VOBJ_TYPE_OLE,   eOle );
784     aOpts.SetObjMode( VOBJ_TYPE_CHART, eChart );
785     aOpts.SetObjMode( VOBJ_TYPE_DRAW,  eDraw );
786 
787     rD.SetViewOptions( aOpts );
788 }
789 
Standardwidth()790 void ImportExcel::Standardwidth()
791 {
792     sal_uInt16 nScWidth = XclTools::GetScColumnWidth( maStrm.ReaduInt16(), GetCharWidth() );
793     if (!pColRowBuff)
794     {
795         SAL_WARN("sc", "*ImportExcel::Standardwidth(): pColRowBuff is NULL!");
796         return;
797     }
798     pColRowBuff->SetDefWidth( nScWidth, true );
799 }
800 
Shrfmla()801 void ImportExcel::Shrfmla()
802 {
803     switch (mnLastRecId)
804     {
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;
812     }
813 
814     if (!mpLastFormula)
815         // The last FORMULA record should have left this data.
816         return;
817 
818     aIn.Ignore( 8 );
819     sal_uInt16 nLenExpr = aIn.ReaduInt16();
820 
821     // read mark is now on the formula
822 
823     std::unique_ptr<ScTokenArray> pResult;
824 
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;
829 
830     ScAddress aPos(nCol1, nRow1, GetCurrScTab());
831     pFormConv->Reset(aPos);
832     pFormConv->Convert( pResult, maStrm, nLenExpr, true, FT_SharedFormula );
833 
834     if (!pResult)
835     {
836         SAL_WARN("sc", "+ImportExcel::Shrfmla(): ScTokenArray is NULL!");
837         return;
838     }
839 
840     pExcRoot->pShrfmlaBuff->Store(aPos, *pResult);
841 
842     // Create formula cell for the last formula record.
843 
844     ScDocumentImport& rDoc = GetDocImport();
845 
846     ScFormulaCell* pCell = new ScFormulaCell(rD, 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 (std::isfinite(mpLastFormula->mfValue))
853         pCell->SetResultDouble(mpLastFormula->mfValue);
854 
855     GetXFRangeBuffer().SetXF(aPos, mpLastFormula->mnXF);
856     mpLastFormula->mpCell = pCell;
857 }
858 
Mulrk()859 void ImportExcel::Mulrk()
860 {
861     /* rw (2 bytes):  An Rw structure that specifies the row containing the
862        cells with numeric data.
863 
864        colFirst (2 bytes):  A Col structure that specifies the first column in
865        the series of numeric cells within the sheet. The value of colFirst.col
866        MUST be less than or equal to 254.
867 
868        rgrkrec (variable): An array of RkRec structures.  Each element in the
869        array specifies an RkRec in the row. The number of entries in the array
870        MUST be equal to the value given by the following formula:
871 
872        Number of entries in rgrkrec = (colLast.col – colFirst.col +1)
873 
874        colLast (2 bytes):  A Col structure that specifies the last column in
875        the set of numeric cells within the sheet. This colLast.col value MUST
876        be greater than the colFirst.col value.  */
877 
878     XclAddress aXclPos;
879     aIn >> aXclPos;
880 
881     XclAddress aCurrXclPos(aXclPos);
882     while (true)
883     {
884         if (aXclPos.mnCol > aCurrXclPos.mnCol)
885             break;
886         if (aIn.GetRecLeft() <= 2)
887             break;
888 
889         sal_uInt16 nXF = aIn.ReaduInt16();
890         sal_Int32 nRkNum = aIn.ReadInt32();
891 
892         ScAddress aScPos( ScAddress::UNINITIALIZED );
893         if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
894         {
895             GetXFRangeBuffer().SetXF( aScPos, nXF );
896             GetDocImport().setNumericCell(aScPos, XclTools::GetDoubleFromRK(nRkNum));
897         }
898         ++aCurrXclPos.mnCol;
899     }
900 }
901 
Mulblank()902 void ImportExcel::Mulblank()
903 {
904     /* rw (2 bytes):  An Rw structure that specifies a row containing the blank
905        cells.
906 
907        colFirst (2 bytes):  A Col structure that specifies the first column in
908        the series of blank cells within the sheet. The value of colFirst.col
909        MUST be less than or equal to 254.
910 
911        rgixfe (variable): An array of IXFCell structures. Each element of this
912        array contains an IXFCell structure corresponding to a blank cell in the
913        series. The number of entries in the array MUST be equal to the value
914        given by the following formula:
915 
916        Number of entries in rgixfe = (colLast.col – colFirst.col +1)
917 
918        colLast (2 bytes):  A Col structure that specifies the last column in
919        the series of blank cells within the sheet. This colLast.col value MUST
920        be greater than colFirst.col value. */
921 
922     XclAddress aXclPos;
923     aIn >> aXclPos;
924 
925     XclAddress aCurrXclPos(aXclPos);
926     while (true)
927     {
928         if (aXclPos.mnCol > aCurrXclPos.mnCol)
929             break;
930         if (aIn.GetRecLeft() <= 2)
931             break;
932 
933         sal_uInt16 nXF = aIn.ReaduInt16();
934 
935         ScAddress aScPos( ScAddress::UNINITIALIZED );
936         if( GetAddressConverter().ConvertAddress( aScPos, aCurrXclPos, GetCurrScTab(), true ) )
937             GetXFRangeBuffer().SetBlankXF( aScPos, nXF );
938         ++aCurrXclPos.mnCol;
939     }
940 }
941 
Rstring()942 void ImportExcel::Rstring()
943 {
944     XclAddress aXclPos;
945     sal_uInt16 nXFIdx;
946     aIn >> aXclPos;
947     nXFIdx = aIn.ReaduInt16();
948 
949     ScAddress aScPos( ScAddress::UNINITIALIZED );
950     if( !GetAddressConverter().ConvertAddress( aScPos, aXclPos, GetCurrScTab(), true ) )
951         return;
952 
953     // unformatted Unicode string with separate formatting information
954     XclImpString aString;
955     aString.Read( maStrm );
956 
957     // character formatting runs
958     if( !aString.IsRich() )
959         aString.ReadFormats( maStrm );
960 
961     GetXFRangeBuffer().SetXF( aScPos, nXFIdx );
962     XclImpStringHelper::SetToDocument(GetDocImport(), aScPos, *this, aString, nXFIdx);
963 }
964 
Cellmerging()965 void ImportExcel::Cellmerging()
966 {
967     XclImpAddressConverter& rAddrConv = GetAddressConverter();
968     SCTAB nScTab = GetCurrScTab();
969 
970     sal_uInt16 nCount = maStrm.ReaduInt16();
971     sal_uInt16 nIdx = 0;
972     while (true)
973     {
974         if (maStrm.GetRecLeft() < 8)
975             break;
976         if (nIdx >= nCount)
977             break;
978         XclRange aXclRange;
979         maStrm >> aXclRange;    // 16-bit rows and columns
980         ScRange aScRange( ScAddress::UNINITIALIZED );
981         if( rAddrConv.ConvertRange( aScRange, aXclRange, nScTab, nScTab, true ) )
982             GetXFRangeBuffer().SetMerge( aScRange.aStart.Col(), aScRange.aStart.Row(), aScRange.aEnd.Col(), aScRange.aEnd.Row() );
983         ++nIdx;
984     }
985 }
986 
Olesize()987 void ImportExcel::Olesize()
988 {
989     XclRange aXclOleSize( ScAddress::UNINITIALIZED );
990     maStrm.Ignore( 2 );
991     aXclOleSize.Read( maStrm, false );
992 
993     SCTAB nScTab = GetCurrScTab();
994     GetAddressConverter().ConvertRange( maScOleSize, aXclOleSize, nScTab, nScTab, false );
995 }
996 
Row34()997 void ImportExcel::Row34()
998 {
999     sal_uInt16  nRow, nRowHeight, nGrbit, nXF;
1000 
1001     nRow = aIn.ReaduInt16();
1002     aIn.Ignore( 4 );
1003 
1004     SCROW nScRow = static_cast< SCROW >( nRow );
1005 
1006     if( !GetRoot().GetDoc().ValidRow( nScRow ) )
1007         return;
1008 
1009     nRowHeight = aIn.ReaduInt16();  // specify direct in Twips
1010     aIn.Ignore( 4 );
1011 
1012     nRowHeight = nRowHeight & 0x7FFF; // Bit 15: Row Height not changed manually
1013     if( !nRowHeight )
1014         nRowHeight = (GetBiff() == EXC_BIFF2) ? 0x25 : 0x225;
1015 
1016     nGrbit = aIn.ReaduInt16();
1017     nXF = aIn.ReaduInt16();
1018 
1019     sal_uInt8 nLevel = ::extract_value< sal_uInt8 >( nGrbit, 0, 3 );
1020     pRowOutlineBuff->SetLevel( nScRow, nLevel, ::get_flag( nGrbit, EXC_ROW_COLLAPSED ) );
1021     pColRowBuff->SetRowSettings( nScRow, nRowHeight, nGrbit );
1022 
1023     if( nGrbit & EXC_ROW_USEDEFXF )
1024         GetXFRangeBuffer().SetRowDefXF( nScRow, nXF & EXC_ROW_XFMASK );
1025 }
1026 
Bof3()1027 void ImportExcel::Bof3()
1028 {
1029     sal_uInt16 nSubType;
1030     maStrm.DisableDecryption();
1031     maStrm.Ignore( 2 );
1032     nSubType = maStrm.ReaduInt16();
1033 
1034     OSL_ENSURE( nSubType != 0x0100, "*ImportExcel::Bof3(): Biff3 as Workbook?!" );
1035     if( nSubType == 0x0100 )        // Book
1036         pExcRoot->eDateiTyp = Biff3W;
1037     else if( nSubType == 0x0020 )   // Chart
1038         pExcRoot->eDateiTyp = Biff3C;
1039     else if( nSubType == 0x0040 )   // Macro
1040         pExcRoot->eDateiTyp = Biff3M;
1041     else                            // #i51490# Excel interprets invalid indexes as worksheet
1042         pExcRoot->eDateiTyp = Biff3;
1043 }
1044 
Array34()1045 void ImportExcel::Array34()
1046 {
1047     sal_uInt16                  nFirstRow, nLastRow, nFormLen;
1048     sal_uInt8                   nFirstCol, nLastCol;
1049 
1050     nFirstRow = aIn.ReaduInt16();
1051     nLastRow = aIn.ReaduInt16();
1052     nFirstCol = aIn.ReaduInt8();
1053     nLastCol = aIn.ReaduInt8();
1054     aIn.Ignore( (GetBiff() >= EXC_BIFF5) ? 6 : 2 );
1055     nFormLen = aIn.ReaduInt16();
1056 
1057     std::unique_ptr<ScTokenArray> pResult;
1058 
1059     if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
1060     {
1061         // the read mark is now on the formula, length in nFormLen
1062 
1063         pFormConv->Reset( ScAddress( static_cast<SCCOL>(nFirstCol),
1064                     static_cast<SCROW>(nFirstRow), GetCurrScTab() ) );
1065         pFormConv->Convert( pResult, maStrm, nFormLen, true );
1066 
1067         SAL_WARN_IF(!pResult, "sc", "+ImportExcel::Array34(): ScTokenArray is NULL!");
1068     }
1069 
1070     if (pResult)
1071     {
1072         ScDocumentImport& rDoc = GetDocImport();
1073         ScRange aArrayRange(nFirstCol, nFirstRow, GetCurrScTab(), nLastCol, nLastRow, GetCurrScTab());
1074         rDoc.setMatrixCells(aArrayRange, *pResult, formula::FormulaGrammar::GRAM_ENGLISH_XL_A1);
1075     }
1076 }
1077 
Defrowheight345()1078 void ImportExcel::Defrowheight345()
1079 {
1080     sal_uInt16 nFlags, nDefHeight;
1081     nFlags = maStrm.ReaduInt16();
1082     nDefHeight = maStrm.ReaduInt16();
1083 
1084     if (!pColRowBuff)
1085     {
1086         SAL_WARN("sc", "*ImportExcel::Defrowheight345(): pColRowBuff is NULL!");
1087         return;
1088     }
1089 
1090     pColRowBuff->SetDefHeight( nDefHeight, nFlags );
1091 }
1092 
TableOp()1093 void ImportExcel::TableOp()
1094 {
1095     sal_uInt16 nFirstRow, nLastRow;
1096     sal_uInt8 nFirstCol, nLastCol;
1097     sal_uInt16 nGrbit;
1098     sal_uInt16 nInpRow, nInpCol, nInpRow2, nInpCol2;
1099 
1100     nFirstRow = aIn.ReaduInt16();
1101     nLastRow = aIn.ReaduInt16();
1102     nFirstCol = aIn.ReaduInt8();
1103     nLastCol = aIn.ReaduInt8();
1104     nGrbit = aIn.ReaduInt16();
1105     nInpRow = aIn.ReaduInt16();
1106     nInpCol = aIn.ReaduInt16();
1107     nInpRow2 = aIn.ReaduInt16();
1108     nInpCol2 = aIn.ReaduInt16();
1109 
1110     if (utl::ConfigManager::IsFuzzing())
1111     {
1112         //shrink to smallish arbitrary value to not timeout
1113         nLastRow = std::min<sal_uInt16>(nLastRow, MAXROW_30);
1114     }
1115 
1116     if( GetRoot().GetDoc().ValidColRow( nLastCol, nLastRow ) )
1117     {
1118         if( nFirstCol && nFirstRow )
1119         {
1120             ScTabOpParam aTabOpParam;
1121             aTabOpParam.meMode = (nGrbit & EXC_TABLEOP_BOTH) ? ScTabOpParam::Both : ((nGrbit & EXC_TABLEOP_ROW) ? ScTabOpParam::Row : ScTabOpParam::Column);
1122             sal_uInt16 nCol = nFirstCol - 1;
1123             sal_uInt16 nRow = nFirstRow - 1;
1124             SCTAB nTab = GetCurrScTab();
1125             switch (aTabOpParam.meMode)
1126             {
1127                 case ScTabOpParam::Column:
1128                     aTabOpParam.aRefFormulaCell.Set(
1129                             static_cast<SCCOL>(nFirstCol),
1130                             static_cast<SCROW>(nFirstRow - 1), nTab, false,
1131                             false, false );
1132                     aTabOpParam.aRefFormulaEnd.Set(
1133                             static_cast<SCCOL>(nLastCol),
1134                             static_cast<SCROW>(nFirstRow - 1), nTab, false,
1135                             false, false );
1136                     aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol),
1137                             static_cast<SCROW>(nInpRow), nTab, false, false,
1138                             false );
1139                     nRow++;
1140                 break;
1141                 case ScTabOpParam::Row:
1142                     aTabOpParam.aRefFormulaCell.Set(
1143                             static_cast<SCCOL>(nFirstCol - 1),
1144                             static_cast<SCROW>(nFirstRow), nTab, false, false,
1145                             false );
1146                     aTabOpParam.aRefFormulaEnd.Set(
1147                             static_cast<SCCOL>(nFirstCol - 1),
1148                             static_cast<SCROW>(nLastRow), nTab, false, false,
1149                             false );
1150                     aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1151                             static_cast<SCROW>(nInpRow), nTab, false, false,
1152                             false );
1153                     nCol++;
1154                 break;
1155                 case ScTabOpParam::Both:     // TWO-INPUT
1156                     aTabOpParam.aRefFormulaCell.Set(
1157                             static_cast<SCCOL>(nFirstCol - 1),
1158                             static_cast<SCROW>(nFirstRow - 1), nTab, false,
1159                             false, false );
1160                     aTabOpParam.aRefRowCell.Set( static_cast<SCCOL>(nInpCol),
1161                             static_cast<SCROW>(nInpRow), nTab, false, false,
1162                             false );
1163                     aTabOpParam.aRefColCell.Set( static_cast<SCCOL>(nInpCol2),
1164                             static_cast<SCROW>(nInpRow2), nTab, false, false,
1165                             false );
1166                 break;
1167             }
1168 
1169             ScDocumentImport& rDoc = GetDocImport();
1170             ScRange aTabOpRange(nCol, nRow, nTab, nLastCol, nLastRow, nTab);
1171             rDoc.setTableOpCells(aTabOpRange, aTabOpParam);
1172         }
1173     }
1174     else
1175     {
1176         bTabTruncated = true;
1177         GetTracer().TraceInvalidRow(nLastRow, rD.MaxRow());
1178     }
1179 }
1180 
Bof4()1181 void ImportExcel::Bof4()
1182 {
1183     sal_uInt16 nSubType;
1184     maStrm.DisableDecryption();
1185     maStrm.Ignore( 2 );
1186     nSubType = maStrm.ReaduInt16();
1187 
1188     if( nSubType == 0x0100 )        // Book
1189         pExcRoot->eDateiTyp = Biff4W;
1190     else if( nSubType == 0x0020 )   // Chart
1191         pExcRoot->eDateiTyp = Biff4C;
1192     else if( nSubType == 0x0040 )   // Macro
1193         pExcRoot->eDateiTyp = Biff4M;
1194     else                            // #i51490# Excel interprets invalid indexes as worksheet
1195         pExcRoot->eDateiTyp = Biff4;
1196 }
1197 
Bof5()1198 void ImportExcel::Bof5()
1199 {
1200     //POST: eDateiTyp = Type of the file to be read
1201     sal_uInt16      nSubType, nVers;
1202     BiffTyp     eDatei;
1203 
1204     maStrm.DisableDecryption();
1205     nVers = maStrm.ReaduInt16();
1206     nSubType = maStrm.ReaduInt16(  );
1207 
1208     switch( nSubType )
1209     {
1210         case 0x0005:    eDatei = Biff5W;    break;  // workbook globals
1211         case 0x0006:    eDatei = Biff5V;    break;  // VB module
1212         case 0x0020:    eDatei = Biff5C;    break;  // chart
1213         case 0x0040:    eDatei = Biff5M4;   break;  // macro sheet
1214         case 0x0010:                                // worksheet
1215         default:        eDatei = Biff5;     break;  // tdf#144732 Excel interprets invalid indexes as worksheet
1216     }
1217 
1218     if( nVers == 0x0600 && (GetBiff() == EXC_BIFF8) )
1219         eDatei = static_cast<BiffTyp>( eDatei - Biff5 + Biff8 );
1220 
1221     pExcRoot->eDateiTyp = eDatei;
1222 }
1223 
EndSheet()1224 void ImportExcel::EndSheet()
1225 {
1226     pExcRoot->pExtSheetBuff->Reset();
1227 
1228     if( GetBiff() <= EXC_BIFF5 )
1229     {
1230         pExcRoot->pExtNameBuff->Reset();
1231         mnLastRefIdx = 0;
1232     }
1233 
1234     FinalizeTable();
1235 }
1236 
NewTable()1237 void ImportExcel::NewTable()
1238 {
1239     SCTAB nTab = GetCurrScTab();
1240     if( nTab > 0 && !rD.HasTable( nTab ) )
1241         rD.MakeTable( nTab );
1242 
1243     if (nTab == 0 && GetBiff() == EXC_BIFF2)
1244     {
1245         // For Excel 2.1 Worksheet file, we need to set the file name as the
1246         // sheet name.
1247         INetURLObject aURL(GetDocUrl());
1248         rD.RenameTab(0, aURL.getBase());
1249     }
1250 
1251     pExcRoot->pShrfmlaBuff->Clear();
1252     maLastFormulaCells.clear();
1253     mpLastFormula = nullptr;
1254 
1255     InitializeTable( nTab );
1256 
1257     XclImpOutlineDataBuffer* pNewItem = new XclImpOutlineDataBuffer( GetRoot(), nTab );
1258     pOutlineListBuffer->push_back( std::unique_ptr<XclImpOutlineDataBuffer>(pNewItem) );
1259     pExcRoot->pColRowBuff = pColRowBuff = pNewItem->GetColRowBuff();
1260     pColOutlineBuff = pNewItem->GetColOutline();
1261     pRowOutlineBuff = pNewItem->GetRowOutline();
1262 }
1263 
ErrorToFormula(bool bErrOrVal,sal_uInt8 nError,double & rVal)1264 std::unique_ptr<ScTokenArray> ImportExcel::ErrorToFormula( bool bErrOrVal, sal_uInt8 nError, double& rVal )
1265 {
1266     return pFormConv->GetBoolErr( XclTools::ErrorToEnum( rVal, bErrOrVal, nError ) );
1267 }
1268 
AdjustRowHeight()1269 void ImportExcel::AdjustRowHeight()
1270 {
1271     /*  Speed up chart import: import all sheets without charts, then
1272         update row heights (here), last load all charts -> do not any longer
1273         update inside of ScDocShell::ConvertFrom() (causes update of existing
1274         charts during each and every change of row height). */
1275     if( ScModelObj* pDocObj = GetDocModelObj() )
1276         pDocObj->UpdateAllRowHeights();
1277 }
1278 
PostDocLoad()1279 void ImportExcel::PostDocLoad()
1280 {
1281     /*  Set automatic page numbering in Default page style (default is "page number = 1").
1282         Otherwise hidden tables (i.e. for scenarios) which have Default page style will
1283         break automatic page numbering. */
1284     if( SfxStyleSheetBase* pStyleSheet = GetStyleSheetPool().Find( ScResId( STR_STYLENAME_STANDARD ), SfxStyleFamily::Page ) )
1285         pStyleSheet->GetItemSet().Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, 0 ) );
1286 
1287     // outlines for all sheets, sets hidden rows and columns (#i11776# after filtered ranges)
1288     for (auto& rxBuffer : *pOutlineListBuffer)
1289         rxBuffer->Convert();
1290 
1291     // document view settings (before visible OLE area)
1292     GetDocViewSettings().Finalize();
1293 
1294     // process all drawing objects (including OLE, charts, controls; after hiding rows/columns; before visible OLE area)
1295     GetObjectManager().ConvertObjects();
1296 
1297     // visible area (used if this document is an embedded OLE object)
1298     if( SfxObjectShell* pDocShell = GetDocShell() )
1299     {
1300         // visible area if embedded
1301         const ScExtDocSettings& rDocSett = GetExtDocOptions().GetDocSettings();
1302         SCTAB nDisplScTab = rDocSett.mnDisplTab;
1303 
1304         /*  #i44077# If a new OLE object is inserted from file, there is no
1305             OLESIZE record in the Excel file. Calculate used area from file
1306             contents (used cells and drawing objects). */
1307         if( !maScOleSize.IsValid() )
1308         {
1309             // used area of displayed sheet (cell contents)
1310             if( const ScExtTabSettings* pTabSett = GetExtDocOptions().GetTabSettings( nDisplScTab ) )
1311                 maScOleSize = pTabSett->maUsedArea;
1312             // add all valid drawing objects
1313             ScRange aScObjArea = GetObjectManager().GetUsedArea( nDisplScTab );
1314             if( aScObjArea.IsValid() )
1315                 maScOleSize.ExtendTo( aScObjArea );
1316         }
1317 
1318         // valid size found - set it at the document
1319         if( maScOleSize.IsValid() )
1320         {
1321             pDocShell->SetVisArea( GetDoc().GetMMRect(
1322                 maScOleSize.aStart.Col(), maScOleSize.aStart.Row(),
1323                 maScOleSize.aEnd.Col(), maScOleSize.aEnd.Row(), nDisplScTab ) );
1324             GetDoc().SetVisibleTab( nDisplScTab );
1325         }
1326     }
1327 
1328     // open forms in alive mode (has no effect, if no controls in document)
1329     if( ScModelObj* pDocObj = GetDocModelObj() )
1330         pDocObj->setPropertyValue( SC_UNO_APPLYFMDES, uno::Any( false ) );
1331 
1332     // enables extended options to be set to the view after import
1333     GetExtDocOptions().SetChanged( true );
1334 
1335     // root data owns the extended document options -> create a new object
1336     GetDoc().SetExtDocOptions( std::make_unique<ScExtDocOptions>( GetExtDocOptions() ) );
1337 
1338     const SCTAB     nLast = rD.GetTableCount();
1339     const ScRange*      p;
1340 
1341     if( pExcRoot->pPrintRanges->HasRanges() )
1342     {
1343         for( SCTAB n = 0 ; n < nLast ; n++ )
1344         {
1345             p = pExcRoot->pPrintRanges->First(n);
1346             if( p )
1347             {
1348                 rD.ClearPrintRanges( n );
1349                 while( p )
1350                 {
1351                     rD.AddPrintRange( n, *p );
1352                     p = pExcRoot->pPrintRanges->Next();
1353                 }
1354             }
1355             else
1356             {
1357                 // #i4063# no print ranges -> print entire sheet
1358                 rD.SetPrintEntireSheet( n );
1359             }
1360         }
1361         GetTracer().TracePrintRange();
1362     }
1363 
1364     if( !pExcRoot->pPrintTitles->HasRanges() )
1365         return;
1366 
1367     for( SCTAB n = 0 ; n < nLast ; n++ )
1368     {
1369         p = pExcRoot->pPrintTitles->First(n);
1370         if( p )
1371         {
1372             bool    bRowVirgin = true;
1373             bool    bColVirgin = true;
1374 
1375             while( p )
1376             {
1377                 if( p->aStart.Col() == 0 && p->aEnd.Col() == rD.MaxCol() && bRowVirgin )
1378                 {
1379                     rD.SetRepeatRowRange( n, std::unique_ptr<ScRange>(new ScRange(*p)) );
1380                     bRowVirgin = false;
1381                 }
1382 
1383                 if( p->aStart.Row() == 0 && p->aEnd.Row() == rD.MaxRow() && bColVirgin )
1384                 {
1385                     rD.SetRepeatColRange( n, std::unique_ptr<ScRange>(new ScRange(*p)) );
1386                     bColVirgin = false;
1387                 }
1388 
1389                 p = pExcRoot->pPrintTitles->Next();
1390             }
1391         }
1392     }
1393 }
1394 
XclImpOutlineDataBuffer(const XclImpRoot & rRoot,SCTAB nScTab)1395 XclImpOutlineDataBuffer::XclImpOutlineDataBuffer( const XclImpRoot& rRoot, SCTAB nScTab ) :
1396     XclImpRoot( rRoot ),
1397     mxColOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Col() + 1 ) ),
1398     mxRowOutlineBuff( std::make_shared<XclImpOutlineBuffer>( rRoot.GetXclMaxPos().Row() + 1 ) ),
1399     mxColRowBuff( std::make_shared<XclImpColRowSettings>( rRoot ) ),
1400     mnScTab( nScTab )
1401 {
1402 }
1403 
~XclImpOutlineDataBuffer()1404 XclImpOutlineDataBuffer::~XclImpOutlineDataBuffer()
1405 {
1406 }
1407 
Convert()1408 void XclImpOutlineDataBuffer::Convert()
1409 {
1410     mxColOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetColArray() );
1411     mxColOutlineBuff->MakeScOutline();
1412 
1413     mxRowOutlineBuff->SetOutlineArray( &GetDoc().GetOutlineTable( mnScTab, true )->GetRowArray() );
1414     mxRowOutlineBuff->MakeScOutline();
1415 
1416     mxColRowBuff->ConvertHiddenFlags( mnScTab );
1417 }
1418 
1419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1420