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