Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / ui / view / viewfun2.cxx
blob2dd4871d217fff02673cd1fd771da73cad708baf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <comphelper/string.hxx>
22 #include <editeng/eeitem.hxx>
24 #include <sfx2/app.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/fontitem.hxx>
27 #include <editeng/scripttypeitem.hxx>
28 #include <svl/srchitem.hxx>
29 #include <sfx2/linkmgr.hxx>
30 #include <sfx2/dispatch.hxx>
31 #include <sfx2/docfilt.hxx>
32 #include <sfx2/docfile.hxx>
33 #include <sfx2/objitem.hxx>
34 #include <sfx2/viewfrm.hxx>
35 #include <svl/stritem.hxx>
36 #include <svl/zforlist.hxx>
37 #include <svx/svdview.hxx>
38 #include <vcl/msgbox.hxx>
39 #include <vcl/waitobj.hxx>
41 #include <basic/sbstar.hxx>
42 #include <com/sun/star/container/XNameContainer.hpp>
43 #include <com/sun/star/script/XLibraryContainer.hpp>
45 #include "viewfunc.hxx"
47 #include "sc.hrc"
48 #include "globstr.hrc"
50 #include "attrib.hxx"
51 #include "autoform.hxx"
52 #include "cell.hxx" // EnterAutoSum
53 #include "cellmergeoption.hxx"
54 #include "compiler.hxx"
55 #include "docfunc.hxx"
56 #include "docpool.hxx"
57 #include "docsh.hxx"
58 #include "global.hxx"
59 #include "patattr.hxx"
60 #include "printfun.hxx"
61 #include "rangenam.hxx"
62 #include "rangeutl.hxx"
63 #include "refundo.hxx"
64 #include "tablink.hxx"
65 #include "tabvwsh.hxx"
66 #include "uiitems.hxx"
67 #include "undoblk.hxx"
68 #include "undocell.hxx"
69 #include "undotab.hxx"
70 #include "sizedev.hxx"
71 #include "editable.hxx"
72 #include "scmod.hxx"
73 #include "inputhdl.hxx"
74 #include "inputwin.hxx"
75 #include "funcdesc.hxx"
76 #include "docuno.hxx"
77 #include "charthelper.hxx"
78 #include "tabbgcolor.hxx"
79 #include "clipparam.hxx"
81 #include <boost/scoped_ptr.hpp>
82 #include <vector>
83 #include <memory>
85 using namespace com::sun::star;
86 using ::rtl::OUStringBuffer;
87 using ::rtl::OUString;
88 using ::editeng::SvxBorderLine;
90 using ::std::vector;
91 using ::std::auto_ptr;
93 // helper func defined in docfunc.cxx
94 void VBA_DeleteModule( ScDocShell& rDocSh, const rtl::OUString& sModuleName );
96 // STATIC DATA ---------------------------------------------------------------
99 //----------------------------------------------------------------------------
101 sal_Bool ScViewFunc::AdjustBlockHeight( sal_Bool bPaint, ScMarkData* pMarkData )
103 ScDocShell* pDocSh = GetViewData()->GetDocShell();
104 if (!pMarkData)
105 pMarkData = &GetViewData()->GetMarkData();
107 ScDocument* pDoc = pDocSh->GetDocument();
108 SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
109 SCCOLROW nRangeCnt = pMarkData->GetMarkRowRanges( pRanges );
110 if (nRangeCnt == 0)
112 pRanges[0] = pRanges[1] = GetViewData()->GetCurY();
113 nRangeCnt = 1;
116 double nPPTX = GetViewData()->GetPPTX();
117 double nPPTY = GetViewData()->GetPPTY();
118 Fraction aZoomX = GetViewData()->GetZoomX();
119 Fraction aZoomY = GetViewData()->GetZoomY();
121 ScSizeDeviceProvider aProv(pDocSh);
122 if (aProv.IsPrinter())
124 nPPTX = aProv.GetPPTX();
125 nPPTY = aProv.GetPPTY();
126 aZoomX = aZoomY = Fraction( 1, 1 );
129 sal_Bool bAnyChanged = false;
130 ScMarkData::iterator itr = pMarkData->begin(), itrEnd = pMarkData->end();
131 for (; itr != itrEnd; ++itr)
133 SCTAB nTab = *itr;
134 SCCOLROW* pOneRange = pRanges;
135 sal_Bool bChanged = false;
136 SCROW nPaintY = 0;
137 for (SCROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
139 SCROW nStartNo = *(pOneRange++);
140 SCROW nEndNo = *(pOneRange++);
141 if (pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
142 nPPTX, nPPTY, aZoomX, aZoomY, false ))
144 if (!bChanged)
145 nPaintY = nStartNo;
146 bAnyChanged = bChanged = sal_True;
149 if ( bPaint && bChanged )
150 pDocSh->PostPaint( 0, nPaintY, nTab, MAXCOL, MAXROW, nTab,
151 PAINT_GRID | PAINT_LEFT );
153 delete[] pRanges;
155 if ( bPaint && bAnyChanged )
156 pDocSh->UpdateOle(GetViewData());
158 return bAnyChanged;
162 //----------------------------------------------------------------------------
164 sal_Bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bPaint )
166 ScDocShell* pDocSh = GetViewData()->GetDocShell();
167 ScDocument* pDoc = pDocSh->GetDocument();
168 SCTAB nTab = GetViewData()->GetTabNo();
169 double nPPTX = GetViewData()->GetPPTX();
170 double nPPTY = GetViewData()->GetPPTY();
171 Fraction aZoomX = GetViewData()->GetZoomX();
172 Fraction aZoomY = GetViewData()->GetZoomY();
173 sal_uInt16 nOldPixel = 0;
174 if (nStartRow == nEndRow)
175 nOldPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY);
177 ScSizeDeviceProvider aProv(pDocSh);
178 if (aProv.IsPrinter())
180 nPPTX = aProv.GetPPTX();
181 nPPTY = aProv.GetPPTY();
182 aZoomX = aZoomY = Fraction( 1, 1 );
184 sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
185 nPPTX, nPPTY, aZoomX, aZoomY, false );
187 if (bChanged && ( nStartRow == nEndRow ))
189 sal_uInt16 nNewPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY);
190 if ( nNewPixel == nOldPixel )
191 bChanged = false;
194 if ( bPaint && bChanged )
195 pDocSh->PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
196 PAINT_GRID | PAINT_LEFT );
198 return bChanged;
202 //----------------------------------------------------------------------------
204 enum ScAutoSum
206 ScAutoSumNone = 0,
207 ScAutoSumData,
208 ScAutoSumSum
212 static ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow,
213 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
215 ScBaseCell* pCell;
216 pDoc->GetCell( nCol, nRow, nTab, pCell );
217 if ( pCell && pCell->HasValueData() )
219 if ( pCell->GetCellType() == CELLTYPE_FORMULA )
221 ScTokenArray* pCode = ((ScFormulaCell*)pCell)->GetCode();
222 if ( pCode && pCode->GetOuterFuncOpCode() == ocSum )
224 if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend,
225 ScAddress( nCol, nRow, nTab ), eDir ) )
226 return ScAutoSumSum;
229 return ScAutoSumData;
231 return ScAutoSumNone;
235 //----------------------------------------------------------------------------
237 #define SC_AUTOSUM_MAXCOUNT 20
239 static ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow,
240 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
242 sal_uInt16 nCount = 0;
243 while (nCount < SC_AUTOSUM_MAXCOUNT)
245 if ( eDir == DIR_TOP )
247 if (nRow > 0)
248 --nRow;
249 else
250 return ScAutoSumNone;
252 else
254 if (nCol > 0)
255 --nCol;
256 else
257 return ScAutoSumNone;
259 ScAutoSum eSum;
260 if ( (eSum = lcl_IsAutoSumData(
261 pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone )
262 return eSum;
263 ++nCount;
265 return ScAutoSumNone;
268 #undef SC_AUTOSUM_MAXCOUNT
270 //----------------------------------------------------------------------------
272 static bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow,
273 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow )
275 const SCROW nTmp = nRow;
276 ScAutoSum eSkip = ScAutoSumNone;
277 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData &&
278 nRow > nMinRow )
280 --nRow;
282 if ( eSkip == ScAutoSumSum && nRow < nTmp )
284 return true;
286 return false;
289 //----------------------------------------------------------------------------
291 static bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow,
292 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol )
294 const SCCOL nTmp = nCol;
295 ScAutoSum eSkip = ScAutoSumNone;
296 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData &&
297 nCol > nMinCol )
299 --nCol;
301 if ( eSkip == ScAutoSumSum && nCol < nTmp )
303 return true;
305 return false;
308 //----------------------------------------------------------------------------
310 static bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
312 const ScAddress aStart = rRange.aStart;
313 const ScAddress aEnd = rRange.aEnd;
314 if ( aStart.Col() != aEnd.Col() )
316 return false;
319 const SCTAB nTab = aEnd.Tab();
320 const SCCOL nCol = aEnd.Col();
321 SCROW nEndRow = aEnd.Row();
322 SCROW nStartRow = nEndRow;
323 SCCOLROW nExtend = 0;
324 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ );
326 if ( eSum == ScAutoSumSum )
328 bool bContinue = false;
331 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
332 nEndRow = static_cast< SCROW >( nExtend );
333 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) == true )
335 nStartRow = nEndRow;
337 } while ( bContinue );
339 else
341 while ( nStartRow > aStart.Row() &&
342 lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum )
344 --nStartRow;
346 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
349 return true;
352 //----------------------------------------------------------------------------
354 static bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
356 const ScAddress aStart = rRange.aStart;
357 const ScAddress aEnd = rRange.aEnd;
358 if ( aStart.Row() != aEnd.Row() )
360 return false;
363 const SCTAB nTab = aEnd.Tab();
364 const SCROW nRow = aEnd.Row();
365 SCCOL nEndCol = aEnd.Col();
366 SCCOL nStartCol = nEndCol;
367 SCCOLROW nExtend = 0;
368 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ );
370 if ( eSum == ScAutoSumSum )
372 bool bContinue = false;
375 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
376 nEndCol = static_cast< SCCOL >( nExtend );
377 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) == true )
379 nStartCol = nEndCol;
381 } while ( bContinue );
383 else
385 while ( nStartCol > aStart.Col() &&
386 lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum )
388 --nStartCol;
390 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
393 return true;
396 //----------------------------------------------------------------------------
398 sal_Bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList )
400 ScDocument* pDoc = GetViewData()->GetDocument();
401 SCTAB nTab = GetViewData()->GetTabNo();
403 SCCOL nCol = GetViewData()->GetCurX();
404 SCROW nRow = GetViewData()->GetCurY();
406 SCCOL nStartCol = nCol;
407 SCROW nStartRow = nRow;
408 SCCOL nEndCol = nCol;
409 SCROW nEndRow = nRow;
410 SCCOL nSeekCol = nCol;
411 SCROW nSeekRow = nRow;
412 SCCOLROW nExtend; // will become valid via reference for ScAutoSumSum
414 sal_Bool bCol = false;
415 sal_Bool bRow = false;
417 ScAutoSum eSum;
418 if ( nRow != 0
419 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
420 DIR_TOP, nExtend /*out*/ )) == ScAutoSumData )
421 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
422 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
425 bRow = sal_True;
426 nSeekRow = nRow - 1;
428 else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab,
429 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
431 bCol = sal_True;
432 nSeekCol = nCol - 1;
434 else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone )
435 bRow = sal_True;
436 else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone )
437 bCol = sal_True;
439 if ( bCol || bRow )
441 if ( bRow )
443 nStartRow = nSeekRow; // nSeekRow might be adjusted via reference
444 if ( eSum == ScAutoSumSum )
445 nEndRow = nStartRow; // only sum sums
446 else
447 nEndRow = nRow - 1; // maybe extend data area at bottom
449 else
451 nStartCol = nSeekCol; // nSeekCol might be adjusted vie reference
452 if ( eSum == ScAutoSumSum )
453 nEndCol = nStartCol; // only sum sums
454 else
455 nEndCol = nCol - 1; // maybe extend data area to the right
457 sal_Bool bContinue = false;
460 if ( eSum == ScAutoSumData )
462 if ( bRow )
464 while ( nStartRow != 0 && lcl_IsAutoSumData( pDoc, nCol,
465 nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum )
466 --nStartRow;
468 else
470 while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1,
471 nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum )
472 --nStartCol;
475 rRangeList.Append(
476 ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) );
477 if ( eSum == ScAutoSumSum )
479 if ( bRow )
481 nEndRow = static_cast< SCROW >( nExtend );
482 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) == true )
484 nStartRow = nEndRow;
487 else
489 nEndCol = static_cast< SCCOL >( nExtend );
490 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) == true )
492 nStartCol = nEndCol;
496 } while ( bContinue );
497 return sal_True;
499 return false;
502 //----------------------------------------------------------------------------
504 void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr)
506 String aFormula = GetAutoSumFormula( rRangeList, bSubTotal, rAddr );
507 EnterBlock( aFormula, NULL );
510 //----------------------------------------------------------------------------
512 bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue )
514 ScDocument* pDoc = GetViewData()->GetDocument();
515 const SCTAB nTab = rRange.aStart.Tab();
516 SCCOL nStartCol = rRange.aStart.Col();
517 SCROW nStartRow = rRange.aStart.Row();
518 const SCCOL nEndCol = rRange.aEnd.Col();
519 const SCROW nEndRow = rRange.aEnd.Row();
520 SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData
522 // ignore rows at the top of the given range which don't contain autosum data
523 bool bRowData = false;
524 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
526 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
528 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone )
530 bRowData = true;
531 break;
534 if ( bRowData )
536 nStartRow = nRow;
537 break;
540 if ( !bRowData )
542 return false;
545 // ignore columns at the left of the given range which don't contain autosum data
546 bool bColData = false;
547 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
549 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
551 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone )
553 bColData = true;
554 break;
557 if ( bColData )
559 nStartCol = nCol;
560 break;
563 if ( !bColData )
565 return false;
568 const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow );
569 const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow );
570 bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) );
571 bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) );
573 // find an empty row for entering the result
574 SCROW nInsRow = nEndRow;
575 if ( bRow && !bEndRowEmpty )
577 if ( nInsRow < MAXROW )
579 ++nInsRow;
580 while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) )
582 if ( nInsRow < MAXROW )
584 ++nInsRow;
586 else
588 bRow = false;
589 break;
593 else
595 bRow = false;
599 // find an empty column for entering the result
600 SCCOL nInsCol = nEndCol;
601 if ( bCol && !bEndColEmpty )
603 if ( nInsCol < MAXCOL )
605 ++nInsCol;
606 while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) )
608 if ( nInsCol < MAXCOL )
610 ++nInsCol;
612 else
614 bCol = false;
615 break;
619 else
621 bCol = false;
625 if ( !bRow && !bCol )
627 return false;
630 SCCOL nMarkEndCol = nEndCol;
631 SCROW nMarkEndRow = nEndRow;
633 if ( bRow )
635 // calculate the row sums for all columns of the given range
637 SCROW nSumEndRow = nEndRow;
639 if ( bEndRowEmpty )
641 // the last row of the given range is empty;
642 // don't take into account for calculating the autosum
643 --nSumEndRow;
645 else
647 // increase mark range
648 ++nMarkEndRow;
651 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
653 if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) )
655 ScRangeList aRangeList;
656 const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab );
657 if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) )
659 const String aFormula = GetAutoSumFormula(
660 aRangeList, bSubTotal, ScAddress(nCol, nInsRow, nTab));
661 EnterData( nCol, nInsRow, nTab, aFormula );
667 if ( bCol )
669 // calculate the column sums for all rows of the given range
671 SCCOL nSumEndCol = nEndCol;
673 if ( bEndColEmpty )
675 // the last column of the given range is empty;
676 // don't take into account for calculating the autosum
677 --nSumEndCol;
679 else
681 // increase mark range
682 ++nMarkEndCol;
685 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
687 if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) )
689 ScRangeList aRangeList;
690 const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab );
691 if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) )
693 const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal, ScAddress(nInsCol, nRow, nTab) );
694 EnterData( nInsCol, nRow, nTab, aFormula );
700 // set new mark range and cursor position
701 const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab );
702 MarkRange( aMarkRange, false, bContinue );
703 if ( bSetCursor )
705 SetCursor( nMarkEndCol, nMarkEndRow );
708 return true;
711 //----------------------------------------------------------------------------
713 String ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr )
715 ScViewData* pViewData = GetViewData();
716 ScDocument* pDoc = pViewData->GetDocument();
717 ::boost::scoped_ptr<ScTokenArray> pArray(new ScTokenArray);
719 pArray->AddOpCode(bSubTotal ? ocSubTotal : ocSum);
720 pArray->AddOpCode(ocOpen);
722 if (bSubTotal)
724 pArray->AddDouble(9);
725 pArray->AddOpCode(ocSep);
728 if(!rRangeList.empty())
730 ScRangeList aRangeList = rRangeList;
731 const ScRange* pFirst = aRangeList.front();
732 size_t ListSize = aRangeList.size();
733 for ( size_t i = 0; i < ListSize; ++i )
735 const ScRange* p = aRangeList[i];
736 if (p != pFirst)
737 pArray->AddOpCode(ocSep);
738 ScComplexRefData aRef;
739 aRef.InitRangeRel(*p, rAddr);
740 pArray->AddDoubleReference(aRef);
744 pArray->AddOpCode(ocClose);
746 ScCompiler aComp(pDoc, rAddr, *pArray);
747 aComp.SetGrammar(pDoc->GetGrammar());
748 OUStringBuffer aBuf;
749 aComp.CreateStringFromTokenArray(aBuf);
750 OUString aFormula = aBuf.makeStringAndClear();
751 aBuf.append(sal_Unicode('='));
752 aBuf.append(aFormula);
753 return aBuf.makeStringAndClear();
756 //----------------------------------------------------------------------------
758 void ScViewFunc::EnterBlock( const String& rString, const EditTextObject* pData )
760 // test for multi selection
762 SCCOL nCol = GetViewData()->GetCurX();
763 SCROW nRow = GetViewData()->GetCurY();
764 SCTAB nTab = GetViewData()->GetTabNo();
765 ScMarkData& rMark = GetViewData()->GetMarkData();
766 if ( rMark.IsMultiMarked() )
768 rMark.MarkToSimple();
769 if ( rMark.IsMultiMarked() )
770 { // "Insert into multi selection not possible"
771 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
773 // insert into single cell
774 if ( pData )
775 EnterData( nCol, nRow, nTab, pData );
776 else
777 EnterData( nCol, nRow, nTab, rString );
778 return;
782 ScDocument* pDoc = GetViewData()->GetDocument();
783 String aNewStr = rString;
784 if ( pData )
786 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
787 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
788 aEngine.SetText(*pData);
790 ScEditAttrTester aTester( &aEngine );
791 if (!aTester.NeedsObject())
793 aNewStr = aEngine.GetText();
794 pData = NULL;
798 // Insert via PasteFromClip
800 WaitObject aWait( GetFrameWin() );
802 ScAddress aPos( nCol, nRow, nTab );
804 ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP );
805 pInsDoc->ResetClip( pDoc, nTab );
807 if (aNewStr.GetChar(0) == '=') // Formula ?
809 // SetString not possible, because in Clipboard-Documents nothing will be compiled!
810 ScFormulaCell* pFCell = new ScFormulaCell( pDoc, aPos, aNewStr );
811 pInsDoc->PutCell( nCol, nRow, nTab, pFCell );
813 else if ( pData )
814 pInsDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pData, pDoc, NULL ) );
815 else
816 pInsDoc->SetString( nCol, nRow, nTab, aNewStr );
818 pInsDoc->SetClipArea( ScRange(aPos) );
819 // insert Block, with Undo etc.
820 if ( PasteFromClip( IDF_CONTENTS, pInsDoc, PASTE_NOFUNC, false, false,
821 false, INS_NONE, IDF_ATTRIB ) )
823 const SfxUInt32Item* pItem = (SfxUInt32Item*) pInsDoc->GetAttr(
824 nCol, nRow, nTab, ATTR_VALUE_FORMAT );
825 if ( pItem )
826 { // set number format if incompatible
827 // MarkData was already MarkToSimple'ed in PasteFromClip
828 ScRange aRange;
829 rMark.GetMarkArea( aRange );
830 ScPatternAttr* pPattern = new ScPatternAttr( pDoc->GetPool() );
831 pPattern->GetItemSet().Put( *pItem );
832 short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() );
833 pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark,
834 *pPattern, nNewType );
835 delete pPattern;
839 delete pInsDoc;
843 //----------------------------------------------------------------------------
844 // manual page break
846 void ScViewFunc::InsertPageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos,
847 sal_Bool bSetModified )
849 SCTAB nTab = GetViewData()->GetTabNo();
850 ScAddress aCursor;
851 if (pPos)
852 aCursor = *pPos;
853 else
854 aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
856 sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
857 InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, false );
859 if ( bSuccess && bSetModified )
860 UpdatePageBreakData( true ); // for PageBreak-Mode
864 //----------------------------------------------------------------------------
866 void ScViewFunc::DeletePageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos,
867 sal_Bool bSetModified )
869 SCTAB nTab = GetViewData()->GetTabNo();
870 ScAddress aCursor;
871 if (pPos)
872 aCursor = *pPos;
873 else
874 aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
876 sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
877 RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, false );
879 if ( bSuccess && bSetModified )
880 UpdatePageBreakData( true ); // for PageBreak-Mode
883 //----------------------------------------------------------------------------
885 void ScViewFunc::RemoveManualBreaks()
887 ScDocShell* pDocSh = GetViewData()->GetDocShell();
888 ScDocument* pDoc = pDocSh->GetDocument();
889 SCTAB nTab = GetViewData()->GetTabNo();
890 sal_Bool bUndo(pDoc->IsUndoEnabled());
892 if (bUndo)
894 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
895 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
896 pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pUndoDoc );
897 pDocSh->GetUndoManager()->AddUndoAction(
898 new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) );
901 pDoc->RemoveManualBreaks(nTab);
902 pDoc->UpdatePageBreaks(nTab);
904 UpdatePageBreakData( sal_True );
905 pDocSh->SetDocumentModified();
906 pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
909 //----------------------------------------------------------------------------
911 void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages)
913 ScDocShell* pDocSh = GetViewData()->GetDocShell();
914 SCTAB nTab = GetViewData()->GetTabNo();
915 pDocSh->SetPrintZoom( nTab, nScale, nPages );
918 void ScViewFunc::AdjustPrintZoom()
920 ScRange aRange;
921 if ( GetViewData()->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
922 GetViewData()->GetMarkData().GetMultiMarkArea( aRange );
923 GetViewData()->GetDocShell()->AdjustPrintZoom( aRange );
926 //----------------------------------------------------------------------------
928 void ScViewFunc::SetPrintRanges( sal_Bool bEntireSheet, const String* pPrint,
929 const String* pRepCol, const String* pRepRow,
930 sal_Bool bAddPrint )
932 // on all selected tables
934 ScDocShell* pDocSh = GetViewData()->GetDocShell();
935 ScDocument* pDoc = pDocSh->GetDocument();
936 ScMarkData& rMark = GetViewData()->GetMarkData();
937 SCTAB nTab;
938 sal_Bool bUndo (pDoc->IsUndoEnabled());
940 ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver();
942 ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
944 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
945 for (; itr != itrEnd; ++itr)
947 nTab = *itr;
948 ScRange aRange( 0,0,nTab );
950 // print ranges
952 if( !bAddPrint )
953 pDoc->ClearPrintRanges( nTab );
955 if( bEntireSheet )
957 pDoc->SetPrintEntireSheet( nTab );
959 else if ( pPrint )
961 if ( pPrint->Len() )
963 const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
964 sal_uInt16 nTCount = comphelper::string::getTokenCount(*pPrint, sep);
965 for (sal_uInt16 i=0; i<nTCount; i++)
967 String aToken = pPrint->GetToken(i, sep);
968 if ( aRange.ParseAny( aToken, pDoc, aDetails ) & SCA_VALID )
969 pDoc->AddPrintRange( nTab, aRange );
973 else // NULL = use selection (print range is always set), use empty string to delete all ranges
975 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
977 pDoc->AddPrintRange( nTab, aRange );
979 else if ( rMark.IsMultiMarked() )
981 rMark.MarkToMulti();
982 ScRangeListRef pList( new ScRangeList );
983 rMark.FillRangeListWithMarks( pList, false );
984 for (size_t i = 0, n = pList->size(); i < n; ++i)
986 ScRange* pR = (*pList)[i];
987 pDoc->AddPrintRange(nTab, *pR);
992 // repeat columns
994 if ( pRepCol )
996 if ( !pRepCol->Len() )
997 pDoc->SetRepeatColRange( nTab, NULL );
998 else
999 if ( aRange.ParseAny( *pRepCol, pDoc, aDetails ) & SCA_VALID )
1000 pDoc->SetRepeatColRange( nTab, &aRange );
1003 // repeat rows
1005 if ( pRepRow )
1007 if ( !pRepRow->Len() )
1008 pDoc->SetRepeatRowRange( nTab, NULL );
1009 else
1010 if ( aRange.ParseAny( *pRepRow, pDoc, aDetails ) & SCA_VALID )
1011 pDoc->SetRepeatRowRange( nTab, &aRange );
1015 // undo (for all tables)
1016 if (bUndo)
1018 SCTAB nCurTab = GetViewData()->GetTabNo();
1019 ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver();
1020 pDocSh->GetUndoManager()->AddUndoAction(
1021 new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) );
1024 // update page breaks
1026 itr = rMark.begin();
1027 for (; itr != itrEnd; ++itr)
1028 ScPrintFunc( pDocSh, pDocSh->GetPrinter(), *itr ).UpdatePages();
1030 SfxBindings& rBindings = GetViewData()->GetBindings();
1031 rBindings.Invalidate( SID_DELETE_PRINTAREA );
1033 pDocSh->SetDocumentModified();
1036 //----------------------------------------------------------------------------
1037 // Merge cells
1039 sal_Bool ScViewFunc::TestMergeCells() // pre-test (for menu)
1041 // simple test: sal_True if there's a selection but no multi selection and not filtered
1043 const ScMarkData& rMark = GetViewData()->GetMarkData();
1044 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1046 ScRange aDummy;
1047 return GetViewData()->GetSimpleArea( aDummy) == SC_MARK_SIMPLE;
1049 else
1050 return false;
1054 //----------------------------------------------------------------------------
1056 sal_Bool ScViewFunc::MergeCells( sal_Bool bApi, sal_Bool& rDoContents, sal_Bool bRecord, sal_Bool bCenter )
1058 // Editable- and Being-Nested- test must be at the beginning (in DocFunc too),
1059 // so that the Contents-QueryBox won't appear
1060 ScEditableTester aTester( this );
1061 if (!aTester.IsEditable())
1063 ErrorMessage(aTester.GetMessageId());
1064 return false;
1067 ScMarkData& rMark = GetViewData()->GetMarkData();
1068 rMark.MarkToSimple();
1069 if (!rMark.IsMarked())
1071 ErrorMessage(STR_NOMULTISELECT);
1072 return false;
1075 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1076 ScDocument* pDoc = pDocSh->GetDocument();
1078 ScRange aMarkRange;
1079 rMark.GetMarkArea( aMarkRange );
1080 SCCOL nStartCol = aMarkRange.aStart.Col();
1081 SCROW nStartRow = aMarkRange.aStart.Row();
1082 SCTAB nStartTab = aMarkRange.aStart.Tab();
1083 SCCOL nEndCol = aMarkRange.aEnd.Col();
1084 SCROW nEndRow = aMarkRange.aEnd.Row();
1085 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1086 if ( nStartCol == nEndCol && nStartRow == nEndRow )
1088 // nothing to do
1089 return true;
1092 if ( pDoc->HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1093 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1094 { // "Don't nest merging !"
1095 ErrorMessage(STR_MSSG_MERGECELLS_0);
1096 return false;
1099 // Check for the contents of all selected tables.
1100 bool bAskDialog = false;
1101 ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter);
1102 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1103 for (; itr != itrEnd; ++itr)
1105 SCTAB i = *itr;
1106 aMergeOption.maTabs.insert(i);
1108 if (!pDoc->IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) ||
1109 !pDoc->IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow))
1110 bAskDialog = true;
1113 sal_Bool bOk = true;
1115 if (bAskDialog)
1117 if (!bApi)
1119 MessBox aBox( GetViewData()->GetDialogParent(),
1120 WinBits(WB_YES_NO_CANCEL | WB_DEF_NO),
1121 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
1122 ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) );
1123 sal_uInt16 nRetVal = aBox.Execute();
1125 if ( nRetVal == RET_YES )
1126 rDoContents = sal_True;
1127 else if ( nRetVal == RET_CANCEL )
1128 bOk = false;
1132 if (bOk)
1134 bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi );
1136 if (bOk)
1138 SetCursor( nStartCol, nStartRow );
1139 //DoneBlockMode( sal_False);
1140 Unmark();
1142 pDocSh->UpdateOle(GetViewData());
1143 UpdateInputLine();
1147 return bOk;
1151 //----------------------------------------------------------------------------
1153 sal_Bool ScViewFunc::TestRemoveMerge()
1155 sal_Bool bMerged = false;
1156 ScRange aRange;
1157 if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1159 ScDocument* pDoc = GetViewData()->GetDocument();
1160 if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
1161 bMerged = sal_True;
1163 return bMerged;
1167 //----------------------------------------------------------------------------
1169 static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange)
1171 bool bExtended = false;
1172 if (rOption.mnStartCol > rRange.aStart.Col())
1174 rOption.mnStartCol = rRange.aStart.Col();
1175 bExtended = true;
1177 if (rOption.mnStartRow > rRange.aStart.Row())
1179 rOption.mnStartRow = rRange.aStart.Row();
1180 bExtended = true;
1182 if (rOption.mnEndCol < rRange.aEnd.Col())
1184 rOption.mnEndCol = rRange.aEnd.Col();
1185 bExtended = true;
1187 if (rOption.mnEndRow < rRange.aEnd.Row())
1189 rOption.mnEndRow = rRange.aEnd.Row();
1190 bExtended = true;
1192 return bExtended;
1195 sal_Bool ScViewFunc::RemoveMerge( sal_Bool bRecord )
1197 ScRange aRange;
1198 ScEditableTester aTester( this );
1199 if (!aTester.IsEditable())
1201 ErrorMessage(aTester.GetMessageId());
1202 return false;
1204 else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1206 ScDocument* pDoc = GetViewData()->GetDocument();
1207 ScRange aExtended( aRange );
1208 pDoc->ExtendMerge( aExtended );
1209 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1210 const ScMarkData& rMark = GetViewData()->GetMarkData();
1211 ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row());
1212 bool bExtended = false;
1215 bExtended = false;
1216 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1217 for (; itr != itrEnd; ++itr)
1219 SCTAB i = *itr;
1220 aOption.maTabs.insert(i);
1221 aExtended.aStart.SetTab(i);
1222 aExtended.aEnd.SetTab(i);
1223 pDoc->ExtendMerge(aExtended);
1224 pDoc->ExtendOverlapped(aExtended);
1226 // Expand the current range to be inclusive of all merged
1227 // areas on all sheets.
1228 bExtended = lcl_extendMergeRange(aOption, aExtended);
1231 while (bExtended);
1233 sal_Bool bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord );
1234 aExtended = aOption.getFirstSingleRange();
1235 MarkRange( aExtended );
1237 if (bOk)
1238 pDocSh->UpdateOle(GetViewData());
1240 return sal_True; //! bOk ??
1243 //----------------------------------------------------------------------------
1245 void ScViewFunc::FillSimple( FillDir eDir, bool bRecord )
1247 ScRange aRange;
1248 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1250 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1251 const ScMarkData& rMark = GetViewData()->GetMarkData();
1252 bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, false );
1253 if (bSuccess)
1255 pDocSh->UpdateOle(GetViewData());
1256 UpdateScrollBars();
1259 else
1260 ErrorMessage(STR_NOMULTISELECT);
1263 //----------------------------------------------------------------------------
1265 void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
1266 double fStart, double fStep, double fMax, sal_Bool bRecord )
1268 ScRange aRange;
1269 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1271 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1272 const ScMarkData& rMark = GetViewData()->GetMarkData();
1273 sal_Bool bSuccess = pDocSh->GetDocFunc().
1274 FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd,
1275 fStart, fStep, fMax, bRecord, false );
1276 if (bSuccess)
1278 pDocSh->UpdateOle(GetViewData());
1279 UpdateScrollBars();
1281 // #i97876# Spreadsheet data changes are not notified
1282 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1283 if ( pModelObj && pModelObj->HasChangesListeners() )
1285 ScRangeList aChangeRanges;
1286 aChangeRanges.Append( aRange );
1287 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1291 else
1292 ErrorMessage(STR_NOMULTISELECT);
1295 //----------------------------------------------------------------------------
1297 void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
1298 SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, sal_Bool bRecord )
1300 SCTAB nTab = GetViewData()->GetTabNo();
1301 ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab );
1302 ScRange aSourceRange( aRange );
1303 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1304 const ScMarkData& rMark = GetViewData()->GetMarkData();
1305 sal_Bool bSuccess = pDocSh->GetDocFunc().
1306 FillAuto( aRange, &rMark, eDir, nCount, bRecord, false );
1307 if (bSuccess)
1309 MarkRange( aRange, false ); // aRange was modified in FillAuto
1310 pDocSh->UpdateOle(GetViewData());
1311 UpdateScrollBars();
1313 // #i97876# Spreadsheet data changes are not notified
1314 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1315 if ( pModelObj && pModelObj->HasChangesListeners() )
1317 ScRangeList aChangeRanges;
1318 ScRange aChangeRange( aRange );
1319 switch ( eDir )
1321 case FILL_TO_BOTTOM:
1323 aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 );
1325 break;
1326 case FILL_TO_TOP:
1328 aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 );
1330 break;
1331 case FILL_TO_RIGHT:
1333 aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 );
1335 break;
1336 case FILL_TO_LEFT:
1338 aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 );
1340 break;
1341 default:
1345 break;
1347 aChangeRanges.Append( aChangeRange );
1348 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1353 //----------------------------------------------------------------------------
1355 void ScViewFunc::FillTab( sal_uInt16 nFlags, sal_uInt16 nFunction, sal_Bool bSkipEmpty, sal_Bool bAsLink )
1357 //! allow source sheet to be protected
1358 ScEditableTester aTester( this );
1359 if (!aTester.IsEditable())
1361 ErrorMessage(aTester.GetMessageId());
1362 return;
1365 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1366 ScDocument* pDoc = pDocSh->GetDocument();
1367 ScMarkData& rMark = GetViewData()->GetMarkData();
1368 SCTAB nTab = GetViewData()->GetTabNo();
1369 sal_Bool bUndo(pDoc->IsUndoEnabled());
1371 ScRange aMarkRange;
1372 rMark.MarkToSimple();
1373 sal_Bool bMulti = rMark.IsMultiMarked();
1374 if (bMulti)
1375 rMark.GetMultiMarkArea( aMarkRange );
1376 else if (rMark.IsMarked())
1377 rMark.GetMarkArea( aMarkRange );
1378 else
1379 aMarkRange = ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
1381 ScDocument* pUndoDoc = NULL;
1383 if (bUndo)
1385 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1386 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1388 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1389 for (; itr != itrEnd; ++itr)
1390 if (*itr != nTab )
1392 SCTAB i = *itr;
1393 pUndoDoc->AddUndoTab( i, i );
1394 aMarkRange.aStart.SetTab( i );
1395 aMarkRange.aEnd.SetTab( i );
1396 pDoc->CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc );
1400 if (bMulti)
1401 pDoc->FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1402 else
1404 aMarkRange.aStart.SetTab( nTab );
1405 aMarkRange.aEnd.SetTab( nTab );
1406 pDoc->FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1409 if (bUndo)
1410 { //! for ChangeTrack not until the end
1411 pDocSh->GetUndoManager()->AddUndoAction(
1412 new ScUndoFillTable( pDocSh, rMark,
1413 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab,
1414 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab,
1415 pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) );
1418 pDocSh->PostPaintGridAll();
1419 pDocSh->PostDataChanged();
1422 //----------------------------------------------------------------------------
1424 /** Downward fill of selected cell(s) by double-clicking cross-hair cursor
1426 Extends a current selection down to the last non-empty cell of an adjacent
1427 column when the lower-right corner of the selection is double-clicked. It
1428 uses a left-adjoining non-empty column as a guide if such is available,
1429 otherwise a right-adjoining non-empty column is used.
1431 @author Kohei Yoshida (kohei@openoffice.org)
1433 @return No return value
1435 @see #i12313#
1437 void ScViewFunc::FillCrossDblClick()
1439 ScRange aRange;
1440 GetViewData()->GetSimpleArea( aRange );
1441 aRange.Justify();
1443 SCTAB nTab = GetViewData()->GetCurPos().Tab();
1444 SCCOL nStartX = aRange.aStart.Col();
1445 SCROW nStartY = aRange.aStart.Row();
1446 SCCOL nEndX = aRange.aEnd.Col();
1447 SCROW nEndY = aRange.aEnd.Row();
1449 ScDocument* pDoc = GetViewData()->GetDocument();
1451 // Make sure the selection is not empty
1452 if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) )
1453 return;
1455 if ( nEndY < MAXROW )
1457 if ( nStartX > 0 )
1459 SCCOL nMovX = nStartX - 1;
1460 SCROW nMovY = nStartY;
1462 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1463 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1465 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1467 if ( nMovY > nEndY )
1469 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1470 nMovY - nEndY );
1471 return;
1476 if ( nEndX < MAXCOL )
1478 SCCOL nMovX = nEndX + 1;
1479 SCROW nMovY = nStartY;
1481 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1482 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1484 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1486 if ( nMovY > nEndY )
1488 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1489 nMovY - nEndY );
1490 return;
1497 //----------------------------------------------------------------------------
1499 void ScViewFunc::TransliterateText( sal_Int32 nType )
1501 ScMarkData aFuncMark = GetViewData()->GetMarkData();
1502 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1504 // no selection -> use cursor position
1506 ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1507 aFuncMark.SetMarkArea( ScRange( aCursor ) );
1510 sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
1511 TransliterateText( aFuncMark, nType, sal_True, false );
1512 if (bSuccess)
1514 GetViewData()->GetViewShell()->UpdateInputHandler();
1518 //----------------------------------------------------------------------------
1519 // AutoFormat
1521 ScAutoFormatData* ScViewFunc::CreateAutoFormatData()
1523 ScAutoFormatData* pData = NULL;
1524 SCCOL nStartCol;
1525 SCROW nStartRow;
1526 SCTAB nStartTab;
1527 SCCOL nEndCol;
1528 SCROW nEndRow;
1529 SCTAB nEndTab;
1530 if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1532 if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 )
1534 ScDocument* pDoc = GetViewData()->GetDocument();
1535 pData = new ScAutoFormatData;
1536 pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData );
1539 return pData;
1543 //----------------------------------------------------------------------------
1545 void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, sal_Bool bRecord )
1547 ScRange aRange;
1548 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1550 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1551 ScMarkData& rMark = GetViewData()->GetMarkData();
1553 sal_Bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, false );
1554 if (bSuccess)
1555 pDocSh->UpdateOle(GetViewData());
1557 else
1558 ErrorMessage(STR_NOMULTISELECT);
1562 //----------------------------------------------------------------------------
1563 // Suchen & Ersetzen
1565 void ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem,
1566 sal_Bool bAddUndo, sal_Bool bIsApi )
1568 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1569 ScDocument* pDoc = pDocSh->GetDocument();
1570 ScMarkData& rMark = GetViewData()->GetMarkData();
1571 if (bAddUndo && !pDoc->IsUndoEnabled())
1572 bAddUndo = false;
1574 SCCOL nCol = GetViewData()->GetCurX();
1575 SCROW nRow = GetViewData()->GetCurY();
1576 SCTAB nTab = GetViewData()->GetTabNo();
1577 sal_uInt16 nCommand = pSearchItem->GetCommand();
1578 bool bAllTables = pSearchItem->IsAllTables();
1579 std::set<SCTAB> aOldSelectedTables;
1580 SCTAB nOldTab = nTab;
1581 SCTAB nLastTab = pDoc->GetTableCount() - 1;
1582 SCTAB nStartTab, nEndTab;
1583 if ( bAllTables )
1585 nStartTab = 0;
1586 nEndTab = nLastTab;
1587 std::set<SCTAB> aTmp(rMark.begin(), rMark.end());
1588 aOldSelectedTables.swap(aTmp);
1590 else
1591 { //! at least one is always selected
1592 nStartTab = rMark.GetFirstSelected();
1593 nEndTab = rMark.GetLastSelected();
1596 if ( nCommand == SVX_SEARCHCMD_FIND
1597 || nCommand == SVX_SEARCHCMD_FIND_ALL)
1598 bAddUndo = false;
1600 //! account for bAttrib during Undo !!!
1602 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1603 std::auto_ptr<ScDocument> pUndoDoc;
1604 std::auto_ptr<ScMarkData> pUndoMark;
1605 SAL_WNODEPRECATED_DECLARATIONS_POP
1606 rtl::OUString aUndoStr;
1607 if (bAddUndo)
1609 pUndoMark.reset(new ScMarkData(rMark)); // Mark is being modified
1610 if ( nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1612 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1613 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
1617 if ( bAllTables )
1618 { //! select all, after pUndoMark has been created
1619 for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1621 rMark.SelectTable( j, true );
1625 DoneBlockMode(true); // don't delete mark
1626 InitOwnBlockMode();
1628 // If search starts at the beginning don't ask again whether it shall start at the beginning
1629 bool bFirst = true;
1630 if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() )
1631 bFirst = false;
1633 bool bFound = false;
1634 while (true)
1636 GetFrameWin()->EnterWait();
1637 ScRangeList aMatchedRanges;
1638 if (pDoc->SearchAndReplace(*pSearchItem, nCol, nRow, nTab, rMark, aMatchedRanges, aUndoStr, pUndoDoc.get()))
1640 bFound = true;
1641 bFirst = true;
1642 if (bAddUndo)
1644 GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction(
1645 new ScUndoReplace( GetViewData()->GetDocShell(), *pUndoMark,
1646 nCol, nRow, nTab,
1647 aUndoStr, pUndoDoc.release(), pSearchItem ) );
1650 rMark.ResetMark();
1651 for (size_t i = 0, n = aMatchedRanges.size(); i < n; ++i)
1653 const ScRange& r = *aMatchedRanges[i];
1654 if (r.aStart.Tab() == nTab)
1655 rMark.SetMultiMarkArea(r);
1658 break; // break 'while (TRUE)'
1660 else if ( bFirst && (nCommand == SVX_SEARCHCMD_FIND ||
1661 nCommand == SVX_SEARCHCMD_REPLACE) )
1663 bFirst = false;
1664 sal_uInt16 nRetVal;
1665 GetFrameWin()->LeaveWait();
1666 if ( bIsApi )
1667 nRetVal = RET_NO;
1668 else
1670 // search dialog as parent (if available)
1671 Window* pParent = GetParentOrChild(SID_SEARCH_DLG);
1672 sal_uInt16 nStrId;
1673 if ( pSearchItem->GetBackward() )
1675 if ( nStartTab == nEndTab )
1676 nStrId = STR_MSSG_SEARCHANDREPLACE_1;
1677 else
1678 nStrId = STR_MSSG_SEARCHANDREPLACE_4;
1680 else
1682 if ( nStartTab == nEndTab )
1683 nStrId = STR_MSSG_SEARCHANDREPLACE_2;
1684 else
1685 nStrId = STR_MSSG_SEARCHANDREPLACE_5;
1687 MessBox aBox( pParent, WinBits(WB_YES_NO | WB_DEF_YES),
1688 ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_3 ),
1689 ScGlobal::GetRscString( nStrId ) );
1690 nRetVal = aBox.Execute();
1693 if ( nRetVal == RET_YES )
1695 ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
1696 if (pSearchItem->GetBackward())
1697 nTab = nEndTab;
1698 else
1699 nTab = nStartTab;
1701 else
1703 break; // break 'while (TRUE)'
1706 else // nothing found
1708 if ( nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1710 pDocSh->PostPaintGridAll(); // Mark
1713 GetFrameWin()->LeaveWait();
1714 if (!bIsApi)
1716 // search dialog as parent if available
1717 Window* pParent = GetParentOrChild(SID_SEARCH_DLG);
1718 // "nothing found"
1719 InfoBox aBox( pParent, ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_0 ) );
1720 aBox.Execute();
1723 break; // break 'while (TRUE)'
1725 } // of while true
1727 if (!aOldSelectedTables.empty())
1729 // restore originally selected table
1730 for (SCTAB i = 0; i <= nEndTab; ++i)
1731 rMark.SelectTable(i, false);
1733 std::set<SCTAB>::const_iterator itr = aOldSelectedTables.begin(), itrEnd = aOldSelectedTables.end();
1734 for (; itr != itrEnd; ++itr)
1735 rMark.SelectTable(*itr, true);
1737 if ( bFound )
1738 { // if a table is selected as a "match" it remains selected.
1739 rMark.SelectTable( nTab, true );
1740 // It's a swap if only one table was selected before
1741 //! otherwise now one table more might be selected
1742 if ( aOldSelectedTables.size() == 1 && nTab != nOldTab )
1743 rMark.SelectTable( nOldTab, false );
1747 MarkDataChanged();
1749 if ( bFound )
1751 if ( nTab != GetViewData()->GetTabNo() )
1752 SetTabNo( nTab );
1754 // if nothing is marked, DoneBlockMode, then marking can start
1755 // directly from this place via Shift-Cursor
1756 if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1757 DoneBlockMode(true);
1759 AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
1760 SetCursor( nCol, nRow, true );
1762 if ( nCommand == SVX_SEARCHCMD_REPLACE
1763 || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1765 if ( nCommand == SVX_SEARCHCMD_REPLACE )
1766 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID );
1767 else
1768 pDocSh->PostPaintGridAll();
1769 pDocSh->SetDocumentModified();
1771 else if ( nCommand == SVX_SEARCHCMD_FIND_ALL )
1772 pDocSh->PostPaintGridAll(); // mark
1773 GetFrameWin()->LeaveWait();
1778 //----------------------------------------------------------------------------
1779 // Zielwertsuche
1781 void ScViewFunc::Solve( const ScSolveParam& rParam )
1783 ScDocument* pDoc = GetViewData()->GetDocument();
1785 SCCOL nDestCol = rParam.aRefVariableCell.Col();
1786 SCROW nDestRow = rParam.aRefVariableCell.Row();
1787 SCTAB nDestTab = rParam.aRefVariableCell.Tab();
1789 ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow );
1790 if (!aTester.IsEditable())
1792 ErrorMessage(aTester.GetMessageId());
1793 return;
1796 if ( pDoc )
1798 String aTargetValStr;
1799 if ( rParam.pStrTargetVal != NULL )
1800 aTargetValStr = *(rParam.pStrTargetVal);
1802 String aMsgStr;
1803 String aResStr;
1804 double nSolveResult;
1806 GetFrameWin()->EnterWait();
1808 sal_Bool bExact =
1809 pDoc->Solver(
1810 rParam.aRefFormulaCell.Col(),
1811 rParam.aRefFormulaCell.Row(),
1812 rParam.aRefFormulaCell.Tab(),
1813 nDestCol, nDestRow, nDestTab,
1814 aTargetValStr,
1815 nSolveResult );
1817 GetFrameWin()->LeaveWait();
1819 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1820 sal_uLong nFormat = 0;
1821 const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab );
1822 if ( pPattern )
1823 nFormat = pPattern->GetNumberFormat( pFormatter );
1824 Color* p;
1825 pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p );
1827 if ( bExact )
1829 aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_0 );
1830 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 );
1831 aMsgStr += String( aResStr );
1832 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_2 );
1834 else
1836 aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_3 );
1837 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 );
1838 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_5 );
1839 aMsgStr += String( aResStr );
1840 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_6 );
1843 MessBox aBox( GetViewData()->GetDialogParent(),
1844 WinBits(WB_YES_NO | WB_DEF_NO),
1845 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr );
1846 sal_uInt16 nRetVal = aBox.Execute();
1848 if ( RET_YES == nRetVal )
1849 EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult );
1851 GetViewData()->GetViewShell()->UpdateInputHandler( sal_True );
1856 //----------------------------------------------------------------------------
1857 // multi operation
1859 void ScViewFunc::TabOp( const ScTabOpParam& rParam, sal_Bool bRecord )
1861 ScRange aRange;
1862 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1864 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1865 ScMarkData& rMark = GetViewData()->GetMarkData();
1866 pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, false );
1868 else
1869 ErrorMessage(STR_NOMULTISELECT);
1873 //----------------------------------------------------------------------------
1875 void ScViewFunc::MakeScenario( const String& rName, const String& rComment,
1876 const Color& rColor, sal_uInt16 nFlags )
1878 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1879 ScMarkData& rMark = GetViewData()->GetMarkData();
1880 SCTAB nTab = GetViewData()->GetTabNo();
1882 SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark );
1883 if (nFlags & SC_SCENARIO_COPYALL)
1884 SetTabNo( nNewTab, true ); // SC_SCENARIO_COPYALL -> visible
1885 else
1887 SfxBindings& rBindings = GetViewData()->GetBindings();
1888 rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar
1889 rBindings.Invalidate( SID_TABLES_COUNT );
1890 rBindings.Invalidate( SID_SELECT_SCENARIO );
1891 rBindings.Invalidate( FID_TABLE_SHOW );
1896 //----------------------------------------------------------------------------
1898 void ScViewFunc::ExtendScenario()
1900 ScEditableTester aTester( this );
1901 if (!aTester.IsEditable())
1903 ErrorMessage(aTester.GetMessageId());
1904 return;
1907 // Undo: apply attributes
1909 ScDocument* pDoc = GetViewData()->GetDocument();
1910 ScPatternAttr aPattern( pDoc->GetPool() );
1911 aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
1912 aPattern.GetItemSet().Put( ScProtectionAttr( sal_True ) );
1913 ApplySelectionPattern(aPattern);
1917 //----------------------------------------------------------------------------
1919 void ScViewFunc::UseScenario( const String& rName )
1921 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1922 SCTAB nTab = GetViewData()->GetTabNo();
1924 DoneBlockMode();
1925 InitOwnBlockMode();
1926 pDocSh->UseScenario( nTab, rName );
1930 //----------------------------------------------------------------------------
1931 // Insert table
1933 sal_Bool ScViewFunc::InsertTable( const String& rName, SCTAB nTab, sal_Bool bRecord )
1935 // Order Tabl/Name is inverted for DocFunc
1936 sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
1937 InsertTable( nTab, rName, bRecord, false );
1938 if (bSuccess)
1939 SetTabNo( nTab, sal_True );
1941 return bSuccess;
1944 //----------------------------------------------------------------------------
1945 // Insert tables
1947 sal_Bool ScViewFunc::InsertTables(std::vector<rtl::OUString>& aNames, SCTAB nTab,
1948 SCTAB nCount, sal_Bool bRecord )
1950 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1951 ScDocument* pDoc = pDocSh->GetDocument();
1952 if (bRecord && !pDoc->IsUndoEnabled())
1953 bRecord = false;
1955 WaitObject aWait( GetFrameWin() );
1957 if (bRecord)
1959 pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
1962 bool bFlag=false;
1964 if(aNames.empty())
1966 pDoc->CreateValidTabNames(aNames, nCount);
1968 if (pDoc->InsertTabs(nTab, aNames, false))
1970 pDocSh->Broadcast( ScTablesHint( SC_TABS_INSERTED, nTab, nCount ) );
1971 bFlag = true;
1974 if (bFlag)
1976 if (bRecord)
1977 pDocSh->GetUndoManager()->AddUndoAction(
1978 new ScUndoInsertTables( pDocSh, nTab, aNames));
1980 // Update views
1982 SetTabNo( nTab, true );
1983 pDocSh->PostPaintExtras();
1984 pDocSh->SetDocumentModified();
1985 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
1986 return true;
1988 else
1990 return false;
1995 //----------------------------------------------------------------------------
1997 sal_Bool ScViewFunc::AppendTable( const String& rName, sal_Bool bRecord )
1999 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2000 ScDocument* pDoc = pDocSh->GetDocument();
2001 if (bRecord && !pDoc->IsUndoEnabled())
2002 bRecord = false;
2004 WaitObject aWait( GetFrameWin() );
2006 if (bRecord)
2007 pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
2009 if (pDoc->InsertTab( SC_TAB_APPEND, rName ))
2011 SCTAB nTab = pDoc->GetTableCount()-1;
2012 if (bRecord)
2013 pDocSh->GetUndoManager()->AddUndoAction(
2014 new ScUndoInsertTab( pDocSh, nTab, sal_True, rName));
2015 GetViewData()->InsertTab( nTab );
2016 SetTabNo( nTab, sal_True );
2017 pDocSh->PostPaintExtras();
2018 pDocSh->SetDocumentModified();
2019 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2020 return sal_True;
2022 else
2024 return false;
2029 //----------------------------------------------------------------------------
2031 sal_Bool ScViewFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord )
2033 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2034 ScDocument* pDoc = pDocSh->GetDocument();
2036 sal_Bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, false );
2037 if (bSuccess)
2039 SCTAB nNewTab = nTab;
2040 if ( nNewTab >= pDoc->GetTableCount() )
2041 --nNewTab;
2042 SetTabNo( nNewTab, sal_True );
2044 return bSuccess;
2047 //only use this method for undo for now, all sheets must be connected
2048 //this method doesn't support undo for now, merge it when it with the other method later
2049 bool ScViewFunc::DeleteTables( const SCTAB nTab, SCTAB nSheets )
2051 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2052 ScDocument* pDoc = pDocSh->GetDocument();
2053 bool bVbaEnabled = pDoc->IsInVBAMode();
2054 SCTAB nNewTab = nTab;
2055 WaitObject aWait( GetFrameWin() );
2057 while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) )
2058 --nNewTab;
2060 if (pDoc->DeleteTabs(nTab, nSheets, NULL))
2062 if( bVbaEnabled )
2064 for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
2066 rtl::OUString sCodeName;
2067 bool bHasCodeName = pDoc->GetCodeName( nTab + aTab, sCodeName );
2068 if ( bHasCodeName )
2069 VBA_DeleteModule( *pDocSh, sCodeName );
2073 pDocSh->Broadcast( ScTablesHint( SC_TABS_DELETED, nTab, nSheets ) );
2074 if ( nNewTab >= pDoc->GetTableCount() )
2075 nNewTab = pDoc->GetTableCount() - 1;
2076 SetTabNo( nNewTab, sal_True );
2078 pDocSh->PostPaintExtras();
2079 pDocSh->SetDocumentModified();
2081 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2082 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2083 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2084 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2085 return true;
2087 return false;
2090 sal_Bool ScViewFunc::DeleteTables(const vector<SCTAB> &TheTabs, sal_Bool bRecord )
2092 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2093 ScDocument* pDoc = pDocSh->GetDocument();
2094 sal_Bool bVbaEnabled = pDoc->IsInVBAMode();
2095 SCTAB nNewTab = TheTabs.front();
2096 WaitObject aWait( GetFrameWin() );
2097 if (bRecord && !pDoc->IsUndoEnabled())
2098 bRecord = false;
2099 if ( bVbaEnabled )
2100 bRecord = false;
2102 while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) )
2103 --nNewTab;
2105 sal_Bool bWasLinked = false;
2106 ScDocument* pUndoDoc = NULL;
2107 ScRefUndoData* pUndoData = NULL;
2108 if (bRecord)
2110 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2111 SCTAB nCount = pDoc->GetTableCount();
2113 rtl::OUString aOldName;
2114 for(unsigned int i=0; i<TheTabs.size(); ++i)
2116 SCTAB nTab = TheTabs[i];
2117 if (i==0)
2118 pUndoDoc->InitUndo( pDoc, nTab,nTab, true,true ); // incl. column/fow flags
2119 else
2120 pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/fow flags
2122 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
2123 pDoc->GetName( nTab, aOldName );
2124 pUndoDoc->RenameTab( nTab, aOldName, false );
2125 if (pDoc->IsLinked(nTab))
2127 bWasLinked = sal_True;
2128 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2129 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2130 pDoc->GetLinkTab(nTab),
2131 pDoc->GetLinkRefreshDelay(nTab) );
2133 if ( pDoc->IsScenario(nTab) )
2135 pUndoDoc->SetScenario( nTab, sal_True );
2136 rtl::OUString aComment;
2137 Color aColor;
2138 sal_uInt16 nScenFlags;
2139 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2140 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2141 sal_Bool bActive = pDoc->IsActiveScenario( nTab );
2142 pUndoDoc->SetActiveScenario( nTab, bActive );
2144 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2145 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
2146 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
2148 if ( pDoc->IsTabProtected( nTab ) )
2149 pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab));
2151 // Drawing-Layer is responsible for its Undo !!!
2152 // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
2155 pUndoDoc->AddUndoTab( 0, nCount-1 ); // all Tabs for references
2157 pDoc->BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage
2159 pUndoData = new ScRefUndoData( pDoc );
2162 sal_Bool bDelDone = false;
2164 for(int i=TheTabs.size()-1; i>=0; --i)
2166 rtl::OUString sCodeName;
2167 sal_Bool bHasCodeName = pDoc->GetCodeName( TheTabs[i], sCodeName );
2168 if (pDoc->DeleteTab( TheTabs[i], pUndoDoc ))
2170 bDelDone = sal_True;
2171 if( bVbaEnabled )
2173 if( bHasCodeName )
2175 VBA_DeleteModule( *pDocSh, sCodeName );
2178 pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i] ) );
2181 if (bRecord)
2183 pDocSh->GetUndoManager()->AddUndoAction(
2184 new ScUndoDeleteTab( GetViewData()->GetDocShell(), TheTabs,
2185 pUndoDoc, pUndoData ));
2189 if (bDelDone)
2191 if ( nNewTab >= pDoc->GetTableCount() )
2192 nNewTab = pDoc->GetTableCount() - 1;
2194 SetTabNo( nNewTab, sal_True );
2196 if (bWasLinked)
2198 pDocSh->UpdateLinks(); // update Link-Manager
2199 GetViewData()->GetBindings().Invalidate(SID_LINKS);
2202 pDocSh->PostPaintExtras();
2203 pDocSh->SetDocumentModified();
2206 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2207 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2208 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2209 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2211 else
2213 delete pUndoDoc;
2214 delete pUndoData;
2216 return bDelDone;
2220 //----------------------------------------------------------------------------
2222 sal_Bool ScViewFunc::RenameTable( const String& rName, SCTAB nTab )
2224 // order Table/Name is inverted for DocFunc
2225 sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
2226 RenameTable( nTab, rName, true, false );
2227 if (bSuccess)
2229 // the table name might be part of a formula
2230 GetViewData()->GetViewShell()->UpdateInputHandler();
2232 return bSuccess;
2236 //----------------------------------------------------------------------------
2238 bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab )
2240 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, sal_True, false );
2241 if (bSuccess)
2243 GetViewData()->GetViewShell()->UpdateInputHandler();
2245 return bSuccess;
2248 bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList )
2250 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, sal_True, false );
2251 if (bSuccess)
2253 GetViewData()->GetViewShell()->UpdateInputHandler();
2255 return bSuccess;
2258 //----------------------------------------------------------------------------
2260 void ScViewFunc::InsertAreaLink( const String& rFile,
2261 const String& rFilter, const String& rOptions,
2262 const String& rSource, sal_uLong nRefresh )
2264 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2265 SCCOL nPosX = GetViewData()->GetCurX();
2266 SCROW nPosY = GetViewData()->GetCurY();
2267 SCTAB nTab = GetViewData()->GetTabNo();
2268 ScAddress aPos( nPosX, nPosY, nTab );
2270 pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, false, false );
2274 //----------------------------------------------------------------------------
2276 void ScViewFunc::InsertTableLink( const String& rFile,
2277 const String& rFilter, const String& rOptions,
2278 const String& rTabName )
2280 rtl::OUString aFilterName = rFilter;
2281 rtl::OUString aOpt = rOptions;
2282 rtl::OUString aURL = rFile;
2283 ScDocumentLoader aLoader( aURL, aFilterName, aOpt );
2284 if (!aLoader.IsError())
2286 ScDocShell* pSrcSh = aLoader.GetDocShell();
2287 ScDocument* pSrcDoc = pSrcSh->GetDocument();
2288 SCTAB nTab = MAXTAB+1;
2289 if (!rTabName.Len()) // no name given -> first table
2290 nTab = 0;
2291 else
2293 rtl::OUString aTemp;
2294 SCTAB nCount = pSrcDoc->GetTableCount();
2295 for (SCTAB i=0; i<nCount; i++)
2297 pSrcDoc->GetName( i, aTemp );
2298 if ( aTemp.equals(rTabName) )
2299 nTab = i;
2303 if ( nTab <= MAXTAB )
2304 ImportTables( pSrcSh, 1, &nTab, sal_True,
2305 GetViewData()->GetTabNo() );
2310 //----------------------------------------------------------------------------
2311 // Copy/link tables from another document
2313 void ScViewFunc::ImportTables( ScDocShell* pSrcShell,
2314 SCTAB nCount, const SCTAB* pSrcTabs, sal_Bool bLink,SCTAB nTab )
2316 ScDocument* pSrcDoc = pSrcShell->GetDocument();
2318 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2319 ScDocument* pDoc = pDocSh->GetDocument();
2320 sal_Bool bUndo(pDoc->IsUndoEnabled());
2322 sal_Bool bError = false;
2323 sal_Bool bRefs = false;
2324 sal_Bool bName = false;
2326 if (pSrcDoc->GetDrawLayer())
2327 pDocSh->MakeDrawLayer();
2329 if (bUndo)
2330 pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2332 SCTAB nInsCount = 0;
2333 SCTAB i;
2334 for( i=0; i<nCount; i++ )
2335 { // insert sheets first and update all references
2336 rtl::OUString aName;
2337 pSrcDoc->GetName( pSrcTabs[i], aName );
2338 pDoc->CreateValidTabName( aName );
2339 if ( !pDoc->InsertTab( nTab+i, aName ) )
2341 bError = sal_True; // total error
2342 break; // for
2344 ++nInsCount;
2346 for (i=0; i<nCount && !bError; i++)
2348 SCTAB nSrcTab = pSrcTabs[i];
2349 SCTAB nDestTab1=nTab+i;
2350 sal_uLong nErrVal = pDocSh->TransferTab( *pSrcShell, nSrcTab, nDestTab1,
2351 false, false ); // no insert
2353 switch (nErrVal)
2355 case 0: // internal error or full of errors
2356 bError = true;
2357 break;
2358 case 2:
2359 bRefs = sal_True;
2360 break;
2361 case 3:
2362 bName = sal_True;
2363 break;
2364 case 4:
2365 bRefs = bName = sal_True;
2366 break;
2371 if (bLink)
2373 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
2375 SfxMedium* pMed = pSrcShell->GetMedium();
2376 String aFileName = pMed->GetName();
2377 String aFilterName;
2378 if (pMed->GetFilter())
2379 aFilterName = pMed->GetFilter()->GetFilterName();
2380 String aOptions = ScDocumentLoader::GetOptions(*pMed);
2382 sal_Bool bWasThere = pDoc->HasLink( aFileName, aFilterName, aOptions );
2384 sal_uLong nRefresh = 0;
2385 rtl::OUString aTabStr;
2386 for (i=0; i<nInsCount; i++)
2388 pSrcDoc->GetName( pSrcTabs[i], aTabStr );
2389 pDoc->SetLink( nTab+i, SC_LINK_NORMAL,
2390 aFileName, aFilterName, aOptions, aTabStr, nRefresh );
2393 if (!bWasThere) // Insert link only once per source document
2395 ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh );
2396 pLink->SetInCreate( sal_True );
2397 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName );
2398 pLink->Update();
2399 pLink->SetInCreate( false );
2401 SfxBindings& rBindings = GetViewData()->GetBindings();
2402 rBindings.Invalidate( SID_LINKS );
2407 if (bUndo)
2409 pDocSh->GetUndoManager()->AddUndoAction(
2410 new ScUndoImportTab( pDocSh, nTab, nCount ) );
2413 for (i=0; i<nInsCount; i++)
2414 GetViewData()->InsertTab(nTab);
2415 SetTabNo(nTab,sal_True);
2416 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2417 PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
2419 SfxApplication* pSfxApp = SFX_APP();
2420 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2421 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2423 pDocSh->PostPaintExtras();
2424 pDocSh->PostPaintGridAll();
2425 pDocSh->SetDocumentModified();
2427 if (bRefs)
2428 ErrorMessage(STR_ABSREFLOST);
2429 if (bName)
2430 ErrorMessage(STR_NAMECONFLICT);
2434 //----------------------------------------------------------------------------
2435 // Move/Copy table to another document
2437 void ScViewFunc::MoveTable(
2438 sal_uInt16 nDestDocNo, SCTAB nDestTab, bool bCopy, const rtl::OUString* pNewTabName )
2440 ScDocument* pDoc = GetViewData()->GetDocument();
2441 ScDocShell* pDocShell = GetViewData()->GetDocShell();
2442 ScDocument* pDestDoc = NULL;
2443 ScDocShell* pDestShell = NULL;
2444 ScTabViewShell* pDestViewSh = NULL;
2445 sal_Bool bUndo (pDoc->IsUndoEnabled());
2446 bool bRename = pNewTabName && !pNewTabName->isEmpty();
2448 bool bNewDoc = (nDestDocNo == SC_DOC_NEW);
2449 if ( bNewDoc )
2451 nDestTab = 0; // firstly insert
2453 // execute without SFX_CALLMODE_RECORD, because already contained in move command
2455 String aUrl = rtl::OUString("private:factory/");
2456 aUrl.AppendAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP )); // "scalc"
2457 SfxStringItem aItem( SID_FILE_NAME, aUrl );
2458 SfxStringItem aTarget( SID_TARGETNAME, rtl::OUString("_blank") );
2460 const SfxPoolItem* pRetItem = GetViewData()->GetDispatcher().Execute(
2461 SID_OPENDOC, SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON, &aItem, &aTarget, 0L );
2462 if ( pRetItem )
2464 if ( pRetItem->ISA( SfxObjectItem ) )
2465 pDestShell = PTR_CAST( ScDocShell, ((const SfxObjectItem*)pRetItem)->GetShell() );
2466 else if ( pRetItem->ISA( SfxViewFrameItem ) )
2468 SfxViewFrame* pFrm = ((const SfxViewFrameItem*)pRetItem)->GetFrame();
2469 if (pFrm)
2470 pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() );
2472 if (pDestShell)
2473 pDestViewSh = pDestShell->GetBestViewShell();
2476 else
2477 pDestShell = ScDocShell::GetShellByNum( nDestDocNo );
2479 if (!pDestShell)
2481 OSL_FAIL("Dest-Doc nicht gefunden !!!");
2482 return;
2485 ScMarkData& rMark = GetViewData()->GetMarkData();
2486 if (bRename && rMark.GetSelectCount() != 1)
2488 // Custom sheet name is provided, but more than one sheet is selected.
2489 // We don't support this scenario at the moment.
2490 return;
2493 pDestDoc = pDestShell->GetDocument();
2495 SCTAB nTab = GetViewData()->GetTabNo();
2497 if (pDestDoc != pDoc)
2499 if (bNewDoc)
2501 while (pDestDoc->GetTableCount() > 1)
2502 pDestDoc->DeleteTab(0);
2503 pDestDoc->RenameTab( 0, rtl::OUString("______42_____"),
2504 false );
2507 SCTAB nTabCount = pDoc->GetTableCount();
2508 SCTAB nTabSelCount = rMark.GetSelectCount();
2510 vector<SCTAB> TheTabs;
2512 for(SCTAB i=0; i<nTabCount; ++i)
2514 if(rMark.GetTableSelect(i))
2516 rtl::OUString aTabName;
2517 pDoc->GetName( i, aTabName);
2518 TheTabs.push_back(i);
2519 for(SCTAB j=i+1;j<nTabCount;j++)
2521 if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2523 pDoc->GetName( j, aTabName);
2524 TheTabs.push_back(j);
2525 i=j;
2527 else break;
2532 GetFrameWin()->EnterWait();
2534 if (pDoc->GetDrawLayer())
2535 pDestShell->MakeDrawLayer();
2537 if (!bNewDoc && bUndo)
2538 pDestDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2540 sal_uLong nErrVal =1;
2541 if(nDestTab==SC_TAB_APPEND)
2542 nDestTab=pDestDoc->GetTableCount();
2543 SCTAB nDestTab1=nDestTab;
2544 ScClipParam aParam;
2545 for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 )
2546 { // insert sheets first and update all references
2547 rtl::OUString aName;
2548 if (bRename)
2549 aName = *pNewTabName;
2550 else
2551 pDoc->GetName( TheTabs[j], aName );
2553 pDestDoc->CreateValidTabName( aName );
2554 if ( !pDestDoc->InsertTab( nDestTab1, aName ) )
2556 nErrVal = 0; // total error
2557 break; // for
2559 ScRange aRange( 0, 0, TheTabs[j], MAXCOL, MAXROW, TheTabs[j] );
2560 aParam.maRanges.Append(aRange);
2562 pDoc->SetClipParam(aParam);
2563 if ( nErrVal > 0 )
2565 nDestTab1 = nDestTab;
2566 for(sal_uInt16 i=0; i<TheTabs.size();++i)
2568 nErrVal = pDestShell->TransferTab( *pDocShell, TheTabs[i], static_cast<SCTAB>(nDestTab1), false, false );
2569 nDestTab1++;
2572 rtl::OUString sName;
2573 if (!bNewDoc && bUndo)
2575 pDestDoc->GetName(nDestTab, sName);
2576 pDestShell->GetUndoManager()->AddUndoAction(
2577 new ScUndoImportTab( pDestShell, nDestTab,
2578 static_cast<SCTAB>(TheTabs.size())));
2581 else
2583 pDestShell->GetUndoManager()->Clear();
2586 GetFrameWin()->LeaveWait();
2587 switch (nErrVal)
2589 case 0: // internal error or full of errors
2591 ErrorMessage(STR_TABINSERT_ERROR);
2592 return;
2594 //break;
2595 case 2:
2596 ErrorMessage(STR_ABSREFLOST);
2597 break;
2598 case 3:
2599 ErrorMessage(STR_NAMECONFLICT);
2600 break;
2601 case 4:
2603 ErrorMessage(STR_ABSREFLOST);
2604 ErrorMessage(STR_NAMECONFLICT);
2606 break;
2607 default:
2608 break;
2611 if (!bCopy)
2613 if(nTabCount!=nTabSelCount)
2614 DeleteTables(TheTabs); // incl. Paint & Undo
2615 else
2616 ErrorMessage(STR_TABREMOVE_ERROR);
2619 if (bNewDoc)
2621 // ChartListenerCollection must be updated before DeleteTab
2622 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
2623 pDestDoc->UpdateChartListenerCollection();
2625 pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size())); // old first table
2626 if (pDestViewSh)
2628 // Make sure to clear the cached page view after sheet
2629 // deletion, which still points to the sdr page belonging to
2630 // the deleted sheet.
2631 SdrView* pSdrView = pDestViewSh->GetSdrView();
2632 if (pSdrView)
2633 pSdrView->ClearPageView();
2635 pDestViewSh->TabChanged(); // Pages auf dem Drawing-Layer
2637 pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2638 PAINT_GRID | PAINT_TOP | PAINT_LEFT |
2639 PAINT_EXTRAS | PAINT_SIZE );
2640 // PAINT_SIZE for outline
2642 else
2644 pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) );
2645 pDestShell->PostPaintExtras();
2646 pDestShell->PostPaintGridAll();
2649 TheTabs.clear();
2651 pDestShell->SetDocumentModified();
2652 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2654 else
2656 // Move or copy within the same document.
2657 SCTAB nTabCount = pDoc->GetTableCount();
2659 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2660 auto_ptr< vector<SCTAB> > pSrcTabs(new vector<SCTAB>);
2661 auto_ptr< vector<SCTAB> > pDestTabs(new vector<SCTAB>);
2662 auto_ptr< vector<OUString> > pTabNames(new vector<OUString>);
2663 auto_ptr< vector<OUString> > pDestNames(NULL);
2664 SAL_WNODEPRECATED_DECLARATIONS_POP
2665 pSrcTabs->reserve(nTabCount);
2666 pDestTabs->reserve(nTabCount);
2667 pTabNames->reserve(nTabCount);
2668 rtl::OUString aDestName;
2670 for(SCTAB i=0;i<nTabCount;i++)
2672 if(rMark.GetTableSelect(i))
2674 rtl::OUString aTabName;
2675 pDoc->GetName( i, aTabName);
2676 pTabNames->push_back(aTabName);
2678 for(SCTAB j=i+1;j<nTabCount;j++)
2680 if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2682 pDoc->GetName( j, aTabName);
2683 pTabNames->push_back(aTabName);
2684 i=j;
2686 else break;
2691 if (bCopy && bUndo)
2692 pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2694 pDoc->GetName( nDestTab, aDestName);
2695 SCTAB nDestTab1=nDestTab;
2696 SCTAB nMovTab=0;
2697 for (size_t j = 0, n = pTabNames->size(); j < n; ++j)
2699 nTabCount = pDoc->GetTableCount();
2700 const OUString& rStr = (*pTabNames)[j];
2701 if(!pDoc->GetTable(rStr,nMovTab))
2703 nMovTab=nTabCount;
2705 if(!pDoc->GetTable(aDestName,nDestTab1))
2707 nDestTab1=nTabCount;
2709 pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, false ); // Undo is here
2711 if(bCopy && pDoc->IsScenario(nMovTab))
2713 rtl::OUString aComment;
2714 Color aColor;
2715 sal_uInt16 nFlags;
2717 pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags);
2718 pDoc->SetScenario(nDestTab1,sal_True);
2719 pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags);
2720 sal_Bool bActive = pDoc->IsActiveScenario(nMovTab );
2721 pDoc->SetActiveScenario( nDestTab1, bActive );
2722 sal_Bool bVisible=pDoc->IsVisible(nMovTab);
2723 pDoc->SetVisible(nDestTab1,bVisible );
2726 pSrcTabs->push_back(nMovTab);
2728 if(!bCopy)
2730 if(!pDoc->GetTable(rStr,nDestTab1))
2732 nDestTab1=nTabCount;
2736 pDestTabs->push_back(nDestTab1);
2739 // Rename must be done after all sheets have been moved.
2740 if (bRename)
2742 pDestNames.reset(new vector<OUString>);
2743 size_t n = pDestTabs->size();
2744 pDestNames->reserve(n);
2745 for (size_t j = 0; j < n; ++j)
2747 SCTAB nRenameTab = (*pDestTabs)[j];
2748 rtl::OUString aTabName = *pNewTabName;
2749 pDoc->CreateValidTabName( aTabName );
2750 pDestNames->push_back(aTabName);
2751 pDoc->RenameTab(nRenameTab, aTabName);
2754 else
2755 // No need to keep this around when we are not renaming.
2756 pTabNames.reset();
2758 nTab = GetViewData()->GetTabNo();
2760 if (bUndo)
2762 if (bCopy)
2764 pDocShell->GetUndoManager()->AddUndoAction(
2765 new ScUndoCopyTab(
2766 pDocShell, pSrcTabs.release(), pDestTabs.release(), pDestNames.release()));
2768 else
2770 pDocShell->GetUndoManager()->AddUndoAction(
2771 new ScUndoMoveTab(
2772 pDocShell, pSrcTabs.release(), pDestTabs.release(), pTabNames.release(), pDestNames.release()));
2776 SCTAB nNewTab = nDestTab;
2777 if (nNewTab == SC_TAB_APPEND)
2778 nNewTab = pDoc->GetTableCount()-1;
2779 else if (!bCopy && nTab<nDestTab)
2780 nNewTab--;
2782 SetTabNo( nNewTab, sal_True );
2784 //#i29848# adjust references to data on the copied sheet
2785 if( bCopy )
2786 ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab );
2791 //----------------------------------------------------------------------------
2793 void ScViewFunc::ShowTable( const String& rName )
2795 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2796 ScDocument* pDoc = pDocSh->GetDocument();
2797 sal_Bool bUndo(pDoc->IsUndoEnabled());
2798 sal_Bool bFound = false;
2799 SCTAB nPos = 0;
2800 rtl::OUString aTabName;
2801 SCTAB nCount = pDoc->GetTableCount();
2802 for (SCTAB i=0; i<nCount; i++)
2804 pDoc->GetName( i, aTabName );
2805 if ( aTabName.equals(rName) )
2807 nPos = i;
2808 bFound = sal_True;
2812 if (bFound)
2814 pDoc->SetVisible( nPos, sal_True );
2815 if (bUndo)
2817 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nPos, sal_True ) );
2819 SetTabNo( nPos, sal_True );
2820 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2821 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2822 pDocSh->SetDocumentModified();
2827 //----------------------------------------------------------------------------
2829 void ScViewFunc::HideTable( SCTAB nTab )
2831 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2832 ScDocument* pDoc = pDocSh->GetDocument();
2833 sal_Bool bUndo(pDoc->IsUndoEnabled());
2834 SCTAB nVisible = 0;
2835 SCTAB nCount = pDoc->GetTableCount();
2836 for (SCTAB i=0; i<nCount; i++)
2838 if (pDoc->IsVisible(i))
2839 ++nVisible;
2842 if (nVisible > 1)
2844 pDoc->SetVisible( nTab, false );
2845 if (bUndo)
2847 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nTab, false ) );
2850 // Update views
2851 pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2853 SetTabNo( nTab, sal_True );
2854 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2855 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2856 pDocSh->SetDocumentModified();
2861 //----------------------------------------------------------------------------
2863 void ScViewFunc::InsertSpecialChar( const String& rStr, const Font& rFont )
2865 ScEditableTester aTester( this );
2866 if (!aTester.IsEditable())
2868 ErrorMessage(aTester.GetMessageId());
2869 return;
2872 const sal_Unicode* pChar = rStr.GetBuffer();
2873 ScTabViewShell* pViewShell = GetViewData()->GetViewShell();
2874 SvxFontItem aFontItem( rFont.GetFamily(),
2875 rFont.GetName(),
2876 rFont.GetStyleName(),
2877 rFont.GetPitch(),
2878 rFont.GetCharSet(),
2879 ATTR_FONT );
2881 // if string contains WEAK characters, set all fonts
2882 sal_uInt8 nScript;
2883 ScDocument* pDoc = GetViewData()->GetDocument();
2884 if ( pDoc->HasStringWeakCharacters( rStr ) )
2885 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX;
2886 else
2887 nScript = pDoc->GetStringScriptType( rStr );
2889 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() );
2890 aSetItem.PutItemForScriptType( nScript, aFontItem );
2891 ApplyUserItemSet( aSetItem.GetItemSet() );
2893 while ( *pChar )
2894 pViewShell->TabKeyInput( KeyEvent( *(pChar++), KeyCode() ) );
2898 //----------------------------------------------------------------------------
2900 void ScViewFunc::UpdateLineAttrs( SvxBorderLine& rLine,
2901 const SvxBorderLine* pDestLine,
2902 const SvxBorderLine* pSrcLine,
2903 sal_Bool bColor )
2905 if ( pSrcLine && pDestLine )
2907 if ( bColor )
2909 rLine.SetColor ( pSrcLine->GetColor() );
2910 rLine.SetBorderLineStyle(pDestLine->GetBorderLineStyle());
2911 rLine.SetWidth ( pDestLine->GetWidth() );
2913 else
2915 rLine.SetColor ( pDestLine->GetColor() );
2916 rLine.SetBorderLineStyle(pSrcLine->GetBorderLineStyle());
2917 rLine.SetWidth ( pSrcLine->GetWidth() );
2923 #define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \
2924 pBoxLine = aBoxItem.Get##LINE(); \
2925 if ( pBoxLine ) \
2927 if ( pLine ) \
2929 UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \
2930 aBoxItem.SetLine( &aLine, BOXLINE ); \
2932 else \
2933 aBoxItem.SetLine( NULL, BOXLINE ); \
2937 //----------------------------------------------------------------------------
2939 void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine,
2940 sal_Bool bColorOnly )
2942 // Not editable only due to a matrix? Attribute is ok anyhow.
2943 bool bOnlyNotBecauseOfMatrix;
2944 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2946 ErrorMessage(STR_PROTECTIONERR);
2947 return;
2950 ScDocument* pDoc = GetViewData()->GetDocument();
2951 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
2952 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
2953 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2954 const ScPatternAttr* pSelAttrs = GetSelectionPattern();
2955 const SfxItemSet& rSelItemSet = pSelAttrs->GetItemSet();
2957 const SfxPoolItem* pBorderAttr = NULL;
2958 SfxItemState eItemState = rSelItemSet.GetItemState( ATTR_BORDER, sal_True, &pBorderAttr );
2960 const SfxPoolItem* pTLBRItem = 0;
2961 SfxItemState eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, sal_True, &pTLBRItem );
2963 const SfxPoolItem* pBLTRItem = 0;
2964 SfxItemState eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, sal_True, &pBLTRItem );
2966 // any of the lines visible?
2967 if( (eItemState != SFX_ITEM_DEFAULT) || (eTLBRState != SFX_ITEM_DEFAULT) || (eBLTRState != SFX_ITEM_DEFAULT) )
2969 // none of the lines don't care?
2970 if( (eItemState != SFX_ITEM_DONTCARE) && (eTLBRState != SFX_ITEM_DONTCARE) && (eBLTRState != SFX_ITEM_DONTCARE) )
2972 SfxItemSet* pOldSet = new SfxItemSet(
2973 *(pDoc->GetPool()),
2974 ATTR_PATTERN_START,
2975 ATTR_PATTERN_END );
2976 SfxItemSet* pNewSet = new SfxItemSet(
2977 *(pDoc->GetPool()),
2978 ATTR_PATTERN_START,
2979 ATTR_PATTERN_END );
2981 //------------------------------------------------------------
2982 const SvxBorderLine* pBoxLine = NULL;
2983 SvxBorderLine aLine;
2985 // here pBoxLine is used
2987 if( pBorderAttr )
2989 SvxBoxItem aBoxItem( *(const SvxBoxItem*)pBorderAttr );
2990 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
2992 SET_LINE_ATTRIBUTES(Top,BOX_LINE_TOP)
2993 SET_LINE_ATTRIBUTES(Bottom,BOX_LINE_BOTTOM)
2994 SET_LINE_ATTRIBUTES(Left,BOX_LINE_LEFT)
2995 SET_LINE_ATTRIBUTES(Right,BOX_LINE_RIGHT)
2997 aBoxInfoItem.SetLine( aBoxItem.GetTop(), BOXINFO_LINE_HORI );
2998 aBoxInfoItem.SetLine( aBoxItem.GetLeft(), BOXINFO_LINE_VERT );
2999 aBoxInfoItem.ResetFlags(); // set Lines to Valid
3001 pOldSet->Put( *pBorderAttr );
3002 pNewSet->Put( aBoxItem );
3003 pNewSet->Put( aBoxInfoItem );
3006 if( pTLBRItem && ((const SvxLineItem*)pTLBRItem)->GetLine() )
3008 SvxLineItem aTLBRItem( *(const SvxLineItem*)pTLBRItem );
3009 UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly );
3010 aTLBRItem.SetLine( &aLine );
3011 pOldSet->Put( *pTLBRItem );
3012 pNewSet->Put( aTLBRItem );
3015 if( pBLTRItem && ((const SvxLineItem*)pBLTRItem)->GetLine() )
3017 SvxLineItem aBLTRItem( *(const SvxLineItem*)pBLTRItem );
3018 UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly );
3019 aBLTRItem.SetLine( &aLine );
3020 pOldSet->Put( *pBLTRItem );
3021 pNewSet->Put( aBLTRItem );
3024 ApplyAttributes( pNewSet, pOldSet );
3026 delete pOldSet;
3027 delete pNewSet;
3029 else // if ( eItemState == SFX_ITEM_DONTCARE )
3031 aFuncMark.MarkToMulti();
3032 pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly );
3035 ScRange aMarkRange;
3036 aFuncMark.GetMultiMarkArea( aMarkRange );
3037 SCCOL nStartCol = aMarkRange.aStart.Col();
3038 SCROW nStartRow = aMarkRange.aStart.Row();
3039 SCTAB nStartTab = aMarkRange.aStart.Tab();
3040 SCCOL nEndCol = aMarkRange.aEnd.Col();
3041 SCROW nEndRow = aMarkRange.aEnd.Row();
3042 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3043 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
3044 nEndCol, nEndRow, nEndTab,
3045 PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3047 pDocSh->UpdateOle( GetViewData() );
3048 pDocSh->SetDocumentModified();
3052 #undef SET_LINE_ATTRIBUTES
3054 //----------------------------------------------------------------------------
3056 void ScViewFunc::SetValidation( const ScValidationData& rNew )
3058 ScDocument* pDoc = GetViewData()->GetDocument();
3059 sal_uLong nIndex = pDoc->AddValidationEntry(rNew); // for it there is no Undo
3060 SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex );
3062 ApplyAttr( aItem ); // with Paint and Undo...
3066 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */