xref: /trunk/main/sc/source/filter/xml/xmlsubti.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 // INCLUDE ---------------------------------------------------------------
29 #include "xmlsubti.hxx"
30 #include "global.hxx"
31 #include "xmlstyli.hxx"
32 #include "xmlimprt.hxx"
33 #include "document.hxx"
34 #include "markdata.hxx"
35 #include "XMLConverter.hxx"
36 #include "docuno.hxx"
37 #include "cellsuno.hxx"
38 #include "XMLStylesImportHelper.hxx"
39 #include "sheetdata.hxx"
40 #include "tabprotection.hxx"
41 #include <svx/svdpage.hxx>
42 
43 #include <xmloff/xmltkmap.hxx>
44 #include <xmloff/nmspmap.hxx>
45 #include <xmloff/xmluconv.hxx>
46 #include <xmloff/xmlerror.hxx>
47 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
48 #include <com/sun/star/util/XMergeable.hpp>
49 #include <com/sun/star/sheet/XSheetCellRange.hpp>
50 #include <com/sun/star/sheet/XCellRangeAddressable.hpp>
51 #include <com/sun/star/sheet/CellInsertMode.hpp>
52 #include <com/sun/star/sheet/XCellRangeMovement.hpp>
53 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
54 #include <com/sun/star/container/XNamed.hpp>
55 #include <com/sun/star/util/XProtectable.hpp>
56 #include <com/sun/star/sheet/XArrayFormulaRange.hpp>
57 
58 #include <memory>
59 
60 using ::std::auto_ptr;
61 
62 //------------------------------------------------------------------
63 
64 using namespace com::sun::star;
65 
ScMyTableData(sal_Int32 nSheet,sal_Int32 nCol,sal_Int32 nRow)66 ScMyTableData::ScMyTableData(sal_Int32 nSheet, sal_Int32 nCol, sal_Int32 nRow)
67 	: 	nColsPerCol(nDefaultColCount, 1),
68 		nRealCols(nDefaultColCount + 1, 0),
69 		nRowsPerRow(nDefaultRowCount, 1),
70 		nRealRows(nDefaultRowCount + 1, 0),
71 		nChangedCols()
72 {
73     aTableCellPos.Sheet = sal::static_int_cast<sal_Int16>( nSheet );
74 	aTableCellPos.Column = nCol;
75 	aTableCellPos.Row = nRow;
76 
77 	for (sal_Int32 i = 0; i < 3; ++i)
78 		nRealCols[i] = i;
79 	for (sal_Int32 j = 0; j < 3; ++j)
80 		nRealRows[j] = j;
81 
82 	nSpannedCols = 1;
83 	nColCount = 0;
84 	nSubTableSpanned = 1;
85 }
86 
~ScMyTableData()87 ScMyTableData::~ScMyTableData()
88 {
89 }
90 
AddRow()91 void ScMyTableData::AddRow()
92 {
93 	++aTableCellPos.Row;
94 	if (static_cast<sal_uInt32>(aTableCellPos.Row) >= nRowsPerRow.size())
95 	{
96 		nRowsPerRow.resize(nRowsPerRow.size() + nDefaultRowCount, 1);
97 		nRealRows.resize(nRowsPerRow.size() + nDefaultRowCount + 1, 0);
98 	}
99 	nRealRows[aTableCellPos.Row + 1] = nRealRows[aTableCellPos.Row] + nRowsPerRow[aTableCellPos.Row];
100 }
101 
AddColumn()102 void ScMyTableData::AddColumn()
103 {
104 	++aTableCellPos.Column;
105 	if (static_cast<sal_uInt32>(aTableCellPos.Column) >= nColsPerCol.size())
106 	{
107 		nColsPerCol.resize(nColsPerCol.size() + nDefaultColCount, 1);
108 		nRealCols.resize(nColsPerCol.size() + nDefaultColCount + 1, 0);
109 	}
110 	nRealCols[aTableCellPos.Column + 1] = nRealCols[aTableCellPos.Column] + nColsPerCol[aTableCellPos.Column];
111 }
112 
GetRealCols(const sal_Int32 nIndex,const sal_Bool) const113 sal_Int32 ScMyTableData::GetRealCols(const sal_Int32 nIndex, const sal_Bool /* bIsNormal */) const
114 {
115 	return (nIndex < 0) ? 0 : nRealCols[nIndex];
116 }
117 
GetChangedCols(const sal_Int32 nFromIndex,const sal_Int32 nToIndex) const118 sal_Int32 ScMyTableData::GetChangedCols(const sal_Int32 nFromIndex, const sal_Int32 nToIndex) const
119 {
120 	ScMysalIntList::const_iterator i(nChangedCols.begin());
121 	ScMysalIntList::const_iterator endi(nChangedCols.end());
122 	while ((i != endi) && ((*i < nToIndex) && !(*i >= nFromIndex)))
123 		++i;
124 	if (i == endi)
125 		return -1;
126 	else
127 		if ((*i >= nFromIndex) && (*i < nToIndex))
128 			return *i;
129 		else
130 			return -1;
131 }
132 
SetChangedCols(const sal_Int32 nValue)133 void ScMyTableData::SetChangedCols(const sal_Int32 nValue)
134 {
135 	ScMysalIntList::iterator i(nChangedCols.begin());
136 	ScMysalIntList::iterator endi(nChangedCols.end());
137 	while ((i != endi) && (*i < nValue))
138 	{
139 		++i;
140 	}
141 	if ((i == endi) || (*i != nValue))
142 		nChangedCols.insert(i, nValue);
143 }
144 
145 /*******************************************************************************************************************************/
146 
ScMyTables(ScXMLImport & rTempImport)147 ScMyTables::ScMyTables(ScXMLImport& rTempImport)
148 	: rImport(rTempImport),
149 	aResizeShapes(rTempImport),
150 	nCurrentColStylePos(0),
151 	nCurrentDrawPage( -1 ),
152 	nCurrentXShapes( -1 ),
153 	nTableCount( 0 ),
154 	nCurrentSheet( -1 )
155 {
156     aTableVec.resize(nDefaultTabCount, NULL);
157 }
158 
~ScMyTables()159 ScMyTables::~ScMyTables()
160 {
161 	ScMyTableData* pTable;
162 	while (nTableCount > 0)
163 	{
164 		pTable = aTableVec[nTableCount - 1];
165 		delete pTable;
166 		aTableVec[nTableCount - 1] = NULL;
167 		--nTableCount;
168 	}
169 }
170 
NewSheet(const rtl::OUString & sTableName,const rtl::OUString & sStyleName,const sal_Bool bTempProtection,const rtl::OUString & sTempPassword)171 void ScMyTables::NewSheet(const rtl::OUString& sTableName, const rtl::OUString& sStyleName,
172 						const sal_Bool bTempProtection, const rtl::OUString& sTempPassword)
173 {
174 	if (rImport.GetModel().is())
175 	{
176 		nCurrentColStylePos = 0;
177 		sCurrentSheetName = sTableName;
178 		ScMyTableData* aTable;
179 		while (nTableCount > 0)
180 		{
181 			aTable = aTableVec[nTableCount - 1];
182 			delete aTable;
183 			aTableVec[nTableCount - 1] = NULL;
184 			--nTableCount;
185 		}
186         ++nCurrentSheet;
187 
188 		bProtection = bTempProtection;
189 		sPassword = sTempPassword;
190 		uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( rImport.GetModel(), uno::UNO_QUERY );
191 		if ( xSpreadDoc.is() )
192 		{
193 			uno::Reference <sheet::XSpreadsheets> xSheets(xSpreadDoc->getSheets());
194 			if (xSheets.is())
195 			{
196 				if (nCurrentSheet > 0)
197 				{
198 					try
199 					{
200                         xSheets->insertNewByName(sTableName, sal::static_int_cast<sal_Int16>(nCurrentSheet));
201 					}
202 					catch ( uno::RuntimeException& )
203 					{
204 						ScDocument *pDoc = ScXMLConverter::GetScDocument(rImport.GetModel());
205 						if (pDoc)
206 						{
207 							rImport.LockSolarMutex();
208 							String sTabName(String::CreateFromAscii("Table"));
209 							pDoc->CreateValidTabName(sTabName);
210 							rtl::OUString sOUTabName(sTabName);
211                             xSheets->insertNewByName(sOUTabName, sal::static_int_cast<sal_Int16>(nCurrentSheet));
212 							rImport.UnlockSolarMutex();
213 						}
214 					}
215 				}
216 				uno::Reference <container::XIndexAccess> xIndex( xSheets, uno::UNO_QUERY );
217 				if ( xIndex.is() )
218 				{
219                     xCurrentSheet.set(xIndex->getByIndex(nCurrentSheet), uno::UNO_QUERY);
220 					if ( xCurrentSheet.is() )
221 					{
222 						xCurrentCellRange.set(xCurrentSheet, uno::UNO_QUERY);
223 						if (!(nCurrentSheet > 0))
224 						{
225 							uno::Reference < container::XNamed > xNamed(xCurrentSheet, uno::UNO_QUERY );
226 							if ( xNamed.is() )
227 								try
228 								{
229 									xNamed->setName(sTableName);
230 								}
231 								catch ( uno::RuntimeException& )
232 								{
233 									ScDocument *pDoc = ScXMLConverter::GetScDocument(rImport.GetModel());
234 									if (pDoc)
235 									{
236 										rImport.LockSolarMutex();
237 										String sTabName(String::CreateFromAscii("Table"));
238 										pDoc->CreateValidTabName(sTabName);
239 										rtl::OUString sOUTabName(sTabName);
240 										xNamed->setName(sOUTabName);
241 										rImport.UnlockSolarMutex();
242 									}
243 								}
244 						}
245 						rImport.SetTableStyle(sStyleName);
246 
247                         if ( sStyleName.getLength() )
248                         {
249                             // #i57869# All table style properties for all sheets are now applied here,
250                             // before importing the contents.
251                             // This is needed for the background color.
252                             // Sheet visibility has special handling in ScDocFunc::SetTableVisible to
253                             // allow hiding the first sheet.
254                             // RTL layout is only remembered, not actually applied, so the shapes can
255                             // be loaded before mirroring.
256 
257                             uno::Reference <beans::XPropertySet> xProperties(xCurrentSheet, uno::UNO_QUERY);
258                             if (xProperties.is())
259                             {
260                                 XMLTableStylesContext *pStyles = (XMLTableStylesContext *)rImport.GetAutoStyles();
261                                 if (pStyles)
262                                 {
263                                     XMLTableStyleContext* pStyle = (XMLTableStyleContext *)pStyles->FindStyleChildContext(
264                                         XML_STYLE_FAMILY_TABLE_TABLE, sStyleName, sal_True);
265                                     if (pStyle)
266                                     {
267                                         pStyle->FillPropertySet(xProperties);
268 
269                                         ScSheetSaveData* pSheetData = ScModelObj::getImplementation(rImport.GetModel())->GetSheetSaveData();
270                                         pSheetData->AddTableStyle( sStyleName, ScAddress( 0, 0, (SCTAB)nCurrentSheet ) );
271                                     }
272                                 }
273                             }
274                         }
275 					}
276 
277 				}
278 			}
279 		}
280 	}
281 
282 	NewTable(1);
283 }
284 
IsMerged(const uno::Reference<table::XCellRange> & xCellRange,const sal_Int32 nCol,const sal_Int32 nRow,table::CellRangeAddress & aCellAddress) const285 sal_Bool ScMyTables::IsMerged (const uno::Reference <table::XCellRange>& xCellRange, const sal_Int32 nCol, const sal_Int32 nRow,
286 							table::CellRangeAddress& aCellAddress) const
287 {
288 	uno::Reference <util::XMergeable> xMergeable (xCellRange->getCellRangeByPosition(nCol,nRow,nCol,nRow), uno::UNO_QUERY);
289 	if (xMergeable.is())
290 	{
291 		uno::Reference<sheet::XSheetCellRange> xMergeSheetCellRange (xMergeable, uno::UNO_QUERY);
292 		uno::Reference<sheet::XSpreadsheet> xTable(xMergeSheetCellRange->getSpreadsheet());
293 		uno::Reference<sheet::XSheetCellCursor> xMergeSheetCursor(xTable->createCursorByRange(xMergeSheetCellRange));
294 		if (xMergeSheetCursor.is())
295 		{
296 			xMergeSheetCursor->collapseToMergedArea();
297 			uno::Reference<sheet::XCellRangeAddressable> xMergeCellAddress (xMergeSheetCursor, uno::UNO_QUERY);
298 			if (xMergeCellAddress.is())
299 			{
300 				aCellAddress = xMergeCellAddress->getRangeAddress();
301 				if (aCellAddress.StartColumn == nCol && aCellAddress.EndColumn == nCol &&
302 					aCellAddress.StartRow == nRow && aCellAddress.EndRow == nRow)
303 					return sal_False;
304 				else
305 					return sal_True;
306 			}
307 		}
308 	}
309 	return sal_False;
310 }
311 
UnMerge()312 void ScMyTables::UnMerge()
313 {
314 	if ( xCurrentCellRange.is() )
315 	{
316 		table::CellRangeAddress aCellAddress;
317 		if (IsMerged(xCurrentCellRange, GetRealCellPos().Column, GetRealCellPos().Row, aCellAddress))
318 		{
319 			//unmerge
320 			uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
321 													aCellAddress.EndColumn, aCellAddress.EndRow), uno::UNO_QUERY);
322 			if (xMergeable.is())
323 				xMergeable->merge(sal_False);
324 		}
325 	}
326 }
327 
DoMerge(sal_Int32 nCount)328 void ScMyTables::DoMerge(sal_Int32 nCount)
329 {
330 	if ( xCurrentCellRange.is() )
331 	{
332 		table::CellRangeAddress aCellAddress;
333 		if (IsMerged(xCurrentCellRange, GetRealCellPos().Column, GetRealCellPos().Row, aCellAddress))
334 		{
335 			//unmerge
336 			uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
337 													aCellAddress.EndColumn, aCellAddress.EndRow), uno::UNO_QUERY);
338 			if (xMergeable.is())
339 				xMergeable->merge(sal_False);
340 		}
341 
342 		//merge
343 		uno::Reference <table::XCellRange> xMergeCellRange;
344 		if (nCount == -1)
345 			xMergeCellRange.set(xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
346 													aCellAddress.EndColumn
347 													+ aTableVec[nTableCount - 1]->GetColsPerCol(aTableVec[nTableCount - 1]->GetColumn()) - 1,
348 													aCellAddress.EndRow
349 													+ aTableVec[nTableCount - 1]->GetRowsPerRow(aTableVec[nTableCount - 1]->GetRow()) - 1));
350 		else
351 			xMergeCellRange.set(xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
352 													aCellAddress.StartColumn
353 													+ nCount - 1,
354 													aCellAddress.EndRow));
355 		uno::Reference <util::XMergeable> xMergeable (xMergeCellRange, uno::UNO_QUERY);
356 		if (xMergeable.is())
357 			xMergeable->merge(sal_True);
358 	}
359 }
360 
InsertRow()361 void ScMyTables::InsertRow()
362 {
363 	if ( xCurrentCellRange.is() )
364 	{
365 		table::CellRangeAddress aCellAddress;
366 		sal_Int32 nRow(GetRealCellPos().Row);
367 		for (sal_Int32 j = 0; j < GetRealCellPos().Column - aTableVec[nTableCount - 1]->GetColumn() - 1; ++j)
368 		{
369 			if (IsMerged(xCurrentCellRange, j, nRow - 1, aCellAddress))
370 			{
371 				//unmerge
372 				uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
373 														aCellAddress.EndColumn, aCellAddress.EndRow), uno::UNO_QUERY);
374 				if (xMergeable.is())
375 					xMergeable->merge(sal_False);
376 			}
377 
378 			//merge
379 			uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
380 													aCellAddress.EndColumn, aCellAddress.EndRow + 1), uno::UNO_QUERY);
381 			if (xMergeable.is())
382 				xMergeable->merge(sal_True);
383 			j += aCellAddress.EndColumn - aCellAddress.StartColumn;
384 		}
385 		rImport.GetStylesImportHelper()->InsertRow(nRow, nCurrentSheet, rImport.GetDocument());
386 	}
387 }
388 
NewRow()389 void ScMyTables::NewRow()
390 {
391 	if (nTableCount > 1)
392 		if (aTableVec[nTableCount - 1]->GetRealRows(aTableVec[nTableCount - 1]->GetRow()) >
393 			aTableVec[nTableCount - 2]->GetRowsPerRow(aTableVec[nTableCount - 2]->GetRow()) - 1)
394 		{
395 			if (GetRealCellPos().Column > 0)
396 				InsertRow();
397             for (sal_Int16 i = sal::static_int_cast<sal_Int16>(nTableCount - 1); i > 0; i--)
398 			{
399 				sal_Int32 nRow = aTableVec[i - 1]->GetRow();
400 				aTableVec[i - 1]->SetRowsPerRow(nRow,
401 					aTableVec[i - 1]->GetRowsPerRow(nRow) + 1);
402 				aTableVec[i - 1]->SetRealRows(nRow + 1,
403 					aTableVec[i - 1]->GetRealRows(nRow)
404 					+ aTableVec[i - 1]->GetRowsPerRow(nRow));
405 			}
406 		}
407 }
408 
AddRow()409 void ScMyTables::AddRow()
410 {
411 	aTableVec[nTableCount - 1]->AddRow();
412 	aTableVec[nTableCount - 1]->SetFirstColumn();
413 	sal_Int32 nRow = aTableVec[nTableCount - 1]->GetRow();
414 	if (nRow > 0)
415 		NewRow();
416 	aTableVec[nTableCount - 1]->SetRealRows(nRow + 1,
417 		aTableVec[nTableCount - 1]->GetRealRows(nRow)
418 		+ aTableVec[nTableCount - 1]->GetRowsPerRow(nRow));
419 }
420 
SetRowStyle(const rtl::OUString & rCellStyleName)421 void ScMyTables::SetRowStyle(const rtl::OUString& rCellStyleName)
422 {
423 	rImport.GetStylesImportHelper()->SetRowStyle(rCellStyleName);
424 }
425 
InsertColumn()426 void ScMyTables::InsertColumn()
427 {
428 	if ( xCurrentCellRange.is() )
429 	{
430 		table::CellRangeAddress aCellAddress;
431 		sal_Int32 nCol(GetRealCellPos().Column);
432 		for (sal_Int32 j = 0; j <= GetRealCellPos().Row - aTableVec[nTableCount - 1]->GetRow() - 1; ++j)
433 		{
434 			table::CellRangeAddress aTempCellAddress;
435 			if (IsMerged(xCurrentCellRange, nCol - 1, j, aCellAddress))
436 			{
437 				//unmerge
438 				uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
439 														aCellAddress.EndColumn, aCellAddress.EndRow), uno::UNO_QUERY);
440 				if (xMergeable.is())
441 					xMergeable->merge(sal_False);
442 				aTempCellAddress = aCellAddress;
443 				aTempCellAddress.StartColumn = aTempCellAddress.EndColumn + 1;
444 				aTempCellAddress.EndColumn = aTempCellAddress.StartColumn;
445 			}
446 			else
447 			{
448 				aTempCellAddress = aCellAddress;
449 				aTempCellAddress.StartColumn += 1;
450 				aTempCellAddress.EndColumn = aTempCellAddress.StartColumn;
451 			}
452 
453 			//insert Cell
454 			sheet::CellInsertMode aCellInsertMode(sheet::CellInsertMode_RIGHT);
455 			uno::Reference <sheet::XCellRangeMovement>	xCellRangeMovement (xCurrentSheet, uno::UNO_QUERY);
456 			xCellRangeMovement->insertCells(aTempCellAddress, aCellInsertMode);
457 
458 			//merge
459 			uno::Reference <util::XMergeable> xMergeable (xCurrentCellRange->getCellRangeByPosition(aCellAddress.StartColumn, aCellAddress.StartRow,
460 														aCellAddress.EndColumn + 1, aCellAddress.EndRow), uno::UNO_QUERY);
461 			if (xMergeable.is())
462 				xMergeable->merge(sal_True);
463 			j += aCellAddress.EndRow - aCellAddress.StartRow;
464 		}
465 		rImport.GetStylesImportHelper()->InsertCol(nCol, nCurrentSheet, rImport.GetDocument());
466 	}
467 }
468 
NewColumn(sal_Bool bIsCovered)469 void ScMyTables::NewColumn(sal_Bool bIsCovered)
470 {
471 	if (!bIsCovered)
472 	{
473 		sal_Int32 nColCount(aTableVec[nTableCount - 1]->GetColCount());
474 		sal_Int32 nSpannedCols(aTableVec[nTableCount - 1]->GetSpannedCols());
475 		if ( (nSpannedCols > nColCount) &&
476 			(aTableVec[nTableCount - 1]->GetRow() == 0) &&
477 			(aTableVec[nTableCount - 1]->GetColumn() == 0) )
478 		{
479 			if (nColCount > 0)
480 			{
481 				sal_Int32 FirstColsSpanned(nSpannedCols / nColCount);
482 				sal_Int32 LastColSpanned(FirstColsSpanned
483 					+ (nSpannedCols	% nColCount));
484 				for (sal_Int32 i = 0; i < nColCount - 1; ++i)
485 				{
486 					aTableVec[nTableCount - 1]->SetColsPerCol(i, FirstColsSpanned);
487 					aTableVec[nTableCount - 1]->SetRealCols(i + 1,
488 						aTableVec[nTableCount - 1]->GetRealCols(i)
489 						+ FirstColsSpanned);
490 				}
491 				aTableVec[nTableCount - 1]->SetColsPerCol(nColCount - 1, LastColSpanned);
492 				aTableVec[nTableCount - 1]->SetRealCols(nColCount - 1 + 1,
493 					aTableVec[nTableCount - 1]->GetRealCols(nColCount - 1)
494 					+ LastColSpanned);
495 			}
496 		}
497 		if (aTableVec[nTableCount - 1]->GetRealCols(aTableVec[nTableCount - 1]->GetColumn()) > nSpannedCols - 1)
498 		{
499 			if ( aTableVec[nTableCount - 1]->GetRow() == 0)
500 			{
501 				InsertColumn();
502                 for (sal_Int16 i = sal::static_int_cast<sal_Int16>(nTableCount - 1); i > 0; i--)
503 				{
504 					sal_Int32 nColPos = aTableVec[i - 1]->GetColumn() +
505 						aTableVec[i]->GetSpannedCols() - 1;
506 					aTableVec[i - 1]->SetColsPerCol(nColPos,
507 						aTableVec[i - 1]->GetColsPerCol(nColPos) +
508 						aTableVec[nTableCount - 1]->GetColsPerCol(aTableVec[nTableCount - 1]->GetColumn()));
509 					aTableVec[i - 1]->SetRealCols(nColPos + 1,
510 						aTableVec[i - 1]->GetRealCols(nColPos)
511 						+ aTableVec[i - 1]->GetColsPerCol(nColPos));
512 					aTableVec[i - 1]->SetChangedCols(nColPos);
513 				}
514 			}
515 		}
516 	}
517 }
518 
AddColumn(sal_Bool bIsCovered)519 void ScMyTables::AddColumn(sal_Bool bIsCovered)
520 {
521 	aTableVec[nTableCount - 1]->AddColumn();
522 	if (aTableVec[nTableCount - 1]->GetSubTableSpanned() > 1)
523 		aTableVec[nTableCount - 1]->SetSubTableSpanned(aTableVec[nTableCount - 1]->GetSubTableSpanned() - 1);
524 	else
525 	{
526 		NewColumn(bIsCovered);
527 	//	if (!bIsCovered)
528 			aTableVec[nTableCount - 1]->SetRealCols(aTableVec[nTableCount - 1]->GetColumn() + 1,
529 				aTableVec[nTableCount - 1]->GetRealCols(aTableVec[nTableCount - 1]->GetColumn())
530 				+ aTableVec[nTableCount - 1]->GetColsPerCol(aTableVec[nTableCount - 1]->GetColumn()));
531 		if ((!bIsCovered) || (bIsCovered &&
532 			(aTableVec[nTableCount - 1]->GetColsPerCol(aTableVec[nTableCount - 1]->GetColumn()) > 1)))
533 		{
534 			if ((aTableVec[nTableCount - 1]->GetRowsPerRow(aTableVec[nTableCount - 1]->GetRow()) > 1) ||
535 				(aTableVec[nTableCount - 1]->GetColsPerCol(aTableVec[nTableCount - 1]->GetColumn()) > 1))
536 				DoMerge();
537 		}
538 	}
539 }
540 
NewTable(sal_Int32 nTempSpannedCols)541 void ScMyTables::NewTable(sal_Int32 nTempSpannedCols)
542 {
543 	++nTableCount;
544 	if (static_cast<sal_uInt32>(nTableCount) >= aTableVec.size())
545 		aTableVec.resize(aTableVec.size() + nDefaultTabCount);
546 	ScMyTableData* aTable(new ScMyTableData(nCurrentSheet));
547 	if (nTableCount > 1)
548 	{
549         ScMyTableData* pTableData = aTableVec[nTableCount - 2];
550 		const sal_Int32 nCol(pTableData->GetColumn());
551 		const sal_Int32 nColCount(pTableData->GetColCount());
552 		const sal_Int32 nColsPerCol(pTableData->GetColsPerCol(nCol));
553 		sal_Int32 nSpannedCols(pTableData->GetSpannedCols());
554 		sal_Int32 nTemp(nSpannedCols - nColCount);
555 		sal_Int32 nTemp2(nCol - (nColCount - 1));
556 		if ((nTemp > 0) && (nTemp2 == 0))
557 			nTempSpannedCols *= (nTemp + 1);
558 		else
559 			if (nColsPerCol > 1)
560 				nTempSpannedCols *= nColsPerCol;
561 
562 		sal_Int32 nToMerge;
563 		if (nSpannedCols > nColCount)
564 			nToMerge = pTableData->GetChangedCols(nCol, nCol + nColsPerCol + nSpannedCols - nColCount);
565 		else
566 			nToMerge = pTableData->GetChangedCols(nCol, nCol + nColsPerCol);
567 		if (nToMerge > nCol)
568 			nTempSpannedCols += nToMerge;
569 	}
570 	aTable->SetSpannedCols(nTempSpannedCols);
571 	aTableVec[nTableCount - 1] = aTable;
572 	if (nTableCount > 1)
573 	{
574 		aTableVec[nTableCount - 2]->SetSubTableSpanned(aTable->GetSpannedCols());
575 		UnMerge();
576 	}
577 }
578 
UpdateRowHeights()579 void ScMyTables::UpdateRowHeights()
580 {
581 	if (rImport.GetModel().is())
582 	{
583 		rImport.LockSolarMutex();
584 		// update automatic row heights
585 
586         // For sheets with any kind of shapes (including notes),
587         // update row heights immediately (before setting the positions).
588         // For sheets without shapes, set "pending" flag
589         // and update row heights when a sheet is shown.
590         // The current sheet (from view settings) is always updated immediately.
591 
592         ScDocument* pDoc = ScXMLConverter::GetScDocument(rImport.GetModel());
593         if (pDoc)
594         {
595             SCTAB nCount = pDoc->GetTableCount();
596             ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
597 
598             SCTAB nVisible = static_cast<SCTAB>( rImport.GetVisibleSheet() );
599 
600             ScMarkData aUpdateSheets;
601             for (SCTAB nTab=0; nTab<nCount; ++nTab)
602             {
603                 const SdrPage* pPage = pDrawLayer ? pDrawLayer->GetPage(nTab) : NULL;
604                 if ( nTab == nVisible || ( pPage && pPage->GetObjCount() != 0 ) )
605                     aUpdateSheets.SelectTable( nTab, sal_True );
606                 else
607                     pDoc->SetPendingRowHeights( nTab, sal_True );
608             }
609 
610             if (aUpdateSheets.GetSelectCount())
611             {
612                 pDoc->LockStreamValid( true );      // ignore draw page size (but not formula results)
613                 // #i114839# make sure the output factor is valid for UpdateAllRowHeights
614                 ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(&aUpdateSheets, true);
615                 pDoc->LockStreamValid( false );
616             }
617         }
618 
619 		rImport.UnlockSolarMutex();
620 	}
621 }
622 
DeleteTable()623 void ScMyTables::DeleteTable()
624 {
625 	rImport.LockSolarMutex();
626 
627 	nCurrentColStylePos = 0;
628 	if (nTableCount > 0)
629 	{
630 		ScMyTableData* aTable = aTableVec[nTableCount - 1];
631 		delete aTable;
632 		aTableVec[nTableCount - 1] = NULL;
633 		nTableCount--;
634 	}
635 	if (nTableCount == 0) // only set the styles if all subtables are importet and the table is finished
636 	{
637 		rImport.GetStylesImportHelper()->SetStylesToRanges();
638 		rImport.SetStylesToRangesFinished();
639 	}
640 
641 	//#i48793#; has to be set before protection
642     if (!aMatrixRangeList.empty())
643     {
644         ScMyMatrixRangeList::iterator aItr = aMatrixRangeList.begin();
645         ScMyMatrixRangeList::iterator aEndItr = aMatrixRangeList.end();
646         while(aItr != aEndItr)
647         {
648             SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar);
649             ++aItr;
650         }
651         aMatrixRangeList.clear();
652     }
653 
654 	if (rImport.GetDocument() && bProtection)
655 	{
656 		uno::Sequence<sal_Int8> aPass;
657 		SvXMLUnitConverter::decodeBase64(aPass, sPassword);
658         auto_ptr<ScTableProtection> pProtect(new ScTableProtection);
659         pProtect->setProtected(bProtection);
660         pProtect->setPasswordHash(aPass, PASSHASH_OOO);
661         rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), pProtect.get());
662 	}
663 
664 	rImport.UnlockSolarMutex();
665 
666 	//#95582#; find out whether it was possible to set the sheet name
667 	// test it here, because if it is a linked table the name is changed by importing
668 	// the linking informations
669 	uno::Reference < container::XNamed > xNamed(xCurrentSheet, uno::UNO_QUERY );
670 	if ( xNamed.is() )
671 	{
672 		rtl::OUString sCurrentName(xNamed->getName());
673 		if (sCurrentName != sCurrentSheetName && rImport.GetDocument())
674 		{
675             rImport.GetDocument()->RenameTab( static_cast<SCTAB>(nCurrentSheet),
676 				sCurrentSheetName, sal_False, sal_True);
677 
678 /*			rtl::OUString sErrorMessage(RTL_CONSTASCII_USTRINGPARAM("Could not create a table with the name "));
679 			sErrorMessage += sCurrentSheetName;
680 			sErrorMessage += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(". The new name is "));
681 			sErrorMessage += sCurrentName;
682 			uno::Sequence<rtl::OUString> aSeq(1);
683 			aSeq[0] = sErrorMessage;
684 			uno::Reference<xml::sax::XLocator> xLocator;
685 			rImport.SetError(XMLERROR_API | XMLERROR_FLAG_ERROR, aSeq, rtl::OUString(), xLocator);*/
686 		}
687 	}
688 }
689 
GetRealCellPos()690 table::CellAddress ScMyTables::GetRealCellPos()
691 {
692 	sal_Int32 nRow(0);
693     sal_Int32 nCol(0);
694 	for (sal_Int32 i = 0; i < nTableCount; ++i)
695 	{
696         ScMyTableData* pTableData = aTableVec[i];
697 		nCol += pTableData->GetRealCols(pTableData->GetColumn());
698 		nRow += pTableData->GetRealRows(pTableData->GetRow());
699 	}
700 	aRealCellPos.Row = nRow;
701 	aRealCellPos.Column = nCol;
702     aRealCellPos.Sheet = sal::static_int_cast<sal_Int16>(nCurrentSheet);
703 	return aRealCellPos;
704 }
705 
AddColCount(sal_Int32 nTempColCount)706 void ScMyTables::AddColCount(sal_Int32 nTempColCount)
707 {
708 	aTableVec[nTableCount - 1]->SetColCount(aTableVec[nTableCount - 1]->GetColCount() + nTempColCount);
709 }
710 
AddColStyle(const sal_Int32 nRepeat,const rtl::OUString & rCellStyleName)711 void ScMyTables::AddColStyle(const sal_Int32 nRepeat, const rtl::OUString& rCellStyleName)
712 {
713 	DBG_ASSERT(nTableCount == 1, "not possible to use default styles on columns in subtables");
714 	rImport.GetStylesImportHelper()->AddColumnStyle(rCellStyleName, nCurrentColStylePos, nRepeat);
715 	nCurrentColStylePos += nRepeat;
716 }
717 
GetCurrentXDrawPage()718 uno::Reference< drawing::XDrawPage > ScMyTables::GetCurrentXDrawPage()
719 {
720 	if( (nCurrentSheet != nCurrentDrawPage) || !xDrawPage.is() )
721 	{
722 		uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier( xCurrentSheet, uno::UNO_QUERY );
723 		if( xDrawPageSupplier.is() )
724 			xDrawPage.set(xDrawPageSupplier->getDrawPage());
725         nCurrentDrawPage = sal::static_int_cast<sal_Int16>(nCurrentSheet);
726 	}
727 	return xDrawPage;
728 }
729 
GetCurrentXShapes()730 uno::Reference< drawing::XShapes > ScMyTables::GetCurrentXShapes()
731 {
732 	if( (nCurrentSheet != nCurrentXShapes) || !xShapes.is() )
733 	{
734 		xShapes.set(GetCurrentXDrawPage(), uno::UNO_QUERY);
735 		rImport.GetShapeImport()->startPage(xShapes);
736 		rImport.GetShapeImport()->pushGroupForSorting ( xShapes );
737         nCurrentXShapes = sal::static_int_cast<sal_Int16>(nCurrentSheet);
738 		return xShapes;
739 	}
740 	else
741 		return xShapes;
742 }
743 
HasDrawPage()744 sal_Bool ScMyTables::HasDrawPage()
745 {
746 	return !((nCurrentSheet != nCurrentDrawPage) || !xDrawPage.is());
747 }
748 
HasXShapes()749 sal_Bool ScMyTables::HasXShapes()
750 {
751 	return !((nCurrentSheet != nCurrentXShapes) || !xShapes.is());
752 }
753 
AddShape(uno::Reference<drawing::XShape> & rShape,rtl::OUString * pRangeList,table::CellAddress & rStartAddress,table::CellAddress & rEndAddress,sal_Int32 nEndX,sal_Int32 nEndY)754 void ScMyTables::AddShape(uno::Reference <drawing::XShape>& rShape,
755 	rtl::OUString* pRangeList,
756 	table::CellAddress& rStartAddress, table::CellAddress& rEndAddress,
757 	sal_Int32 nEndX, sal_Int32 nEndY)
758 {
759 	aResizeShapes.AddShape(rShape, pRangeList, rStartAddress, rEndAddress, nEndX, nEndY);
760 }
761 
AddMatrixRange(sal_Int32 nStartColumn,sal_Int32 nStartRow,sal_Int32 nEndColumn,sal_Int32 nEndRow,const rtl::OUString & rFormula,const rtl::OUString & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar)762 void ScMyTables::AddMatrixRange(
763         sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nEndColumn, sal_Int32 nEndRow,
764         const rtl::OUString& rFormula, const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar)
765 {
766     DBG_ASSERT(nEndRow >= nStartRow, "wrong row order");
767     DBG_ASSERT(nEndColumn >= nStartColumn, "wrong column order");
768     table::CellRangeAddress aRange;
769     aRange.StartColumn = nStartColumn;
770     aRange.StartRow = nStartRow;
771     aRange.EndColumn = nEndColumn;
772     aRange.EndRow = nEndRow;
773     aRange.Sheet = sal::static_int_cast<sal_Int16>(nCurrentSheet);
774     ScMatrixRange aMRange(aRange, rFormula, rFormulaNmsp, eGrammar);
775     aMatrixRangeList.push_back(aMRange);
776 }
777 
IsPartOfMatrix(sal_Int32 nColumn,sal_Int32 nRow)778 sal_Bool ScMyTables::IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow)
779 {
780     sal_Bool bResult(sal_False);
781     if (!aMatrixRangeList.empty())
782     {
783         ScMyMatrixRangeList::iterator aItr(aMatrixRangeList.begin());
784         ScMyMatrixRangeList::iterator aEndItr(aMatrixRangeList.end());
785         sal_Bool bReady(sal_False);
786         while(!bReady && aItr != aEndItr)
787         {
788             if (nCurrentSheet > aItr->aRange.Sheet)
789             {
790                 DBG_ERROR("should never happen, because the list should be cleared in DeleteTable");
791                 aItr = aMatrixRangeList.erase(aItr);
792             }
793             else if ((nRow > aItr->aRange.EndRow) && (nColumn > aItr->aRange.EndColumn))
794             {
795                 SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar);
796                 aItr = aMatrixRangeList.erase(aItr);
797             }
798             else if (nColumn < aItr->aRange.StartColumn)
799                 bReady = sal_True;
800             else if (nColumn >= aItr->aRange.StartColumn && nColumn <= aItr->aRange.EndColumn && nRow >= aItr->aRange.StartRow && nRow <= aItr->aRange.EndRow)
801             {
802                 bReady = sal_True;
803                 bResult = sal_True;
804             }
805             else
806                 ++aItr;
807         }
808     }
809     return bResult;
810 }
811 
SetMatrix(const table::CellRangeAddress & rRange,const rtl::OUString & rFormula,const rtl::OUString & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar)812 void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUString& rFormula,
813         const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar)
814 {
815 	uno::Reference <table::XCellRange> xMatrixCellRange(
816 		GetCurrentXCellRange()->getCellRangeByPosition(rRange.StartColumn, rRange.StartRow,
817 					rRange.EndColumn, rRange.EndRow));
818 	if (xMatrixCellRange.is())
819 	{
820 		uno::Reference <sheet::XArrayFormulaRange> xArrayFormulaRange(xMatrixCellRange, uno::UNO_QUERY);
821 		if (xArrayFormulaRange.is())
822         {
823             ScCellRangeObj* pCellRangeObj =
824                 static_cast<ScCellRangeObj*>(ScCellRangesBase::getImplementation(
825                             xMatrixCellRange));
826             if (pCellRangeObj)
827                 pCellRangeObj->SetArrayFormulaWithGrammar( rFormula, rFormulaNmsp, eGrammar);
828         }
829 	}
830 }
831