Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / view / viewfun2.cxx
blob85ec4034a5542fe1cab20e50369c7c63a5c297eb
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/srchdlg.hxx>
38 #include <svx/svdview.hxx>
39 #include <vcl/msgbox.hxx>
40 #include <vcl/waitobj.hxx>
42 #include <basic/sbstar.hxx>
43 #include <com/sun/star/container/XNameContainer.hpp>
44 #include <com/sun/star/script/XLibraryContainer.hpp>
46 #include "viewfunc.hxx"
48 #include "sc.hrc"
49 #include "globstr.hrc"
51 #include "attrib.hxx"
52 #include "autoform.hxx"
53 #include "formulacell.hxx"
54 #include "cellmergeoption.hxx"
55 #include "compiler.hxx"
56 #include "docfunc.hxx"
57 #include "docpool.hxx"
58 #include "docsh.hxx"
59 #include "global.hxx"
60 #include "patattr.hxx"
61 #include "printfun.hxx"
62 #include "rangenam.hxx"
63 #include "rangeutl.hxx"
64 #include "refundo.hxx"
65 #include "table.hxx"
66 #include "tablink.hxx"
67 #include "tabvwsh.hxx"
68 #include "uiitems.hxx"
69 #include "undoblk.hxx"
70 #include "undocell.hxx"
71 #include "undotab.hxx"
72 #include "sizedev.hxx"
73 #include "editable.hxx"
74 #include "scmod.hxx"
75 #include "inputhdl.hxx"
76 #include "inputwin.hxx"
77 #include "funcdesc.hxx"
78 #include "docuno.hxx"
79 #include "charthelper.hxx"
80 #include "tabbgcolor.hxx"
81 #include "clipparam.hxx"
82 #include "prnsave.hxx"
83 #include "searchresults.hxx"
84 #include "tokenarray.hxx"
85 #include <columnspanset.hxx>
86 #include <rowheightcontext.hxx>
88 #include <boost/scoped_ptr.hpp>
89 #include <vector>
90 #include <memory>
92 using namespace com::sun::star;
93 using ::editeng::SvxBorderLine;
95 using ::std::vector;
96 using ::std::auto_ptr;
98 // helper func defined in docfunc.cxx
99 void VBA_DeleteModule( ScDocShell& rDocSh, const OUString& sModuleName );
101 // STATIC DATA ---------------------------------------------------------------
104 bool ScViewFunc::AdjustBlockHeight( bool bPaint, ScMarkData* pMarkData )
106 ScDocShell* pDocSh = GetViewData()->GetDocShell();
107 if (!pMarkData)
108 pMarkData = &GetViewData()->GetMarkData();
110 ScDocument* pDoc = pDocSh->GetDocument();
111 std::vector<sc::ColRowSpan> aMarkedRows = pMarkData->GetMarkedRowSpans();
113 if (aMarkedRows.empty())
115 SCROW nCurRow = GetViewData()->GetCurY();
116 aMarkedRows.push_back(sc::ColRowSpan(nCurRow, nCurRow));
119 double nPPTX = GetViewData()->GetPPTX();
120 double nPPTY = GetViewData()->GetPPTY();
121 Fraction aZoomX = GetViewData()->GetZoomX();
122 Fraction aZoomY = GetViewData()->GetZoomY();
124 ScSizeDeviceProvider aProv(pDocSh);
125 if (aProv.IsPrinter())
127 nPPTX = aProv.GetPPTX();
128 nPPTY = aProv.GetPPTY();
129 aZoomX = aZoomY = Fraction( 1, 1 );
132 sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
133 bool bAnyChanged = false;
134 ScMarkData::iterator itr = pMarkData->begin(), itrEnd = pMarkData->end();
135 for (; itr != itrEnd; ++itr)
137 SCTAB nTab = *itr;
138 bool bChanged = false;
139 SCROW nPaintY = 0;
140 std::vector<sc::ColRowSpan>::const_iterator itRows = aMarkedRows.begin(), itRowsEnd = aMarkedRows.end();
141 for (; itRows != itRowsEnd; ++itRows)
143 SCROW nStartNo = itRows->mnStart;
144 SCROW nEndNo = itRows->mnEnd;
145 if (pDoc->SetOptimalHeight(aCxt, nStartNo, nEndNo, nTab))
147 if (!bChanged)
148 nPaintY = nStartNo;
149 bAnyChanged = bChanged = true;
152 if ( bPaint && bChanged )
153 pDocSh->PostPaint( 0, nPaintY, nTab, MAXCOL, MAXROW, nTab,
154 PAINT_GRID | PAINT_LEFT );
157 if ( bPaint && bAnyChanged )
158 pDocSh->UpdateOle(GetViewData());
160 return bAnyChanged;
164 bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, 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 sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
185 bool bChanged = pDoc->SetOptimalHeight(aCxt, nStartRow, nEndRow, nTab);
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 enum ScAutoSum
204 ScAutoSumNone = 0,
205 ScAutoSumData,
206 ScAutoSumSum
210 static ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow,
211 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
213 ScRefCellValue aCell;
214 aCell.assign(*pDoc, ScAddress(nCol, nRow, nTab));
215 if (aCell.hasNumeric())
217 if (aCell.meType == CELLTYPE_FORMULA)
219 ScTokenArray* pCode = aCell.mpFormula->GetCode();
220 if ( pCode && pCode->GetOuterFuncOpCode() == ocSum )
222 if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend,
223 ScAddress( nCol, nRow, nTab ), eDir ) )
224 return ScAutoSumSum;
227 return ScAutoSumData;
229 return ScAutoSumNone;
233 #define SC_AUTOSUM_MAXCOUNT 20
235 static ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow,
236 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
238 sal_uInt16 nCount = 0;
239 while (nCount < SC_AUTOSUM_MAXCOUNT)
241 if ( eDir == DIR_TOP )
243 if (nRow > 0)
244 --nRow;
245 else
246 return ScAutoSumNone;
248 else
250 if (nCol > 0)
251 --nCol;
252 else
253 return ScAutoSumNone;
255 ScAutoSum eSum;
256 if ( (eSum = lcl_IsAutoSumData(
257 pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone )
258 return eSum;
259 ++nCount;
261 return ScAutoSumNone;
264 #undef SC_AUTOSUM_MAXCOUNT
266 static bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow,
267 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow )
269 const SCROW nTmp = nRow;
270 ScAutoSum eSkip = ScAutoSumNone;
271 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData &&
272 nRow > nMinRow )
274 --nRow;
276 if ( eSkip == ScAutoSumSum && nRow < nTmp )
278 return true;
280 return false;
283 static bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow,
284 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol )
286 const SCCOL nTmp = nCol;
287 ScAutoSum eSkip = ScAutoSumNone;
288 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData &&
289 nCol > nMinCol )
291 --nCol;
293 if ( eSkip == ScAutoSumSum && nCol < nTmp )
295 return true;
297 return false;
300 static bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
302 const ScAddress aStart = rRange.aStart;
303 const ScAddress aEnd = rRange.aEnd;
304 if ( aStart.Col() != aEnd.Col() )
306 return false;
309 const SCTAB nTab = aEnd.Tab();
310 const SCCOL nCol = aEnd.Col();
311 SCROW nEndRow = aEnd.Row();
312 SCROW nStartRow = nEndRow;
313 SCCOLROW nExtend = 0;
314 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ );
316 if ( eSum == ScAutoSumSum )
318 bool bContinue = false;
321 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
322 nEndRow = static_cast< SCROW >( nExtend );
323 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) == true )
325 nStartRow = nEndRow;
327 } while ( bContinue );
329 else
331 while ( nStartRow > aStart.Row() &&
332 lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum )
334 --nStartRow;
336 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
339 return true;
342 static bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
344 const ScAddress aStart = rRange.aStart;
345 const ScAddress aEnd = rRange.aEnd;
346 if ( aStart.Row() != aEnd.Row() )
348 return false;
351 const SCTAB nTab = aEnd.Tab();
352 const SCROW nRow = aEnd.Row();
353 SCCOL nEndCol = aEnd.Col();
354 SCCOL nStartCol = nEndCol;
355 SCCOLROW nExtend = 0;
356 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ );
358 if ( eSum == ScAutoSumSum )
360 bool bContinue = false;
363 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
364 nEndCol = static_cast< SCCOL >( nExtend );
365 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) == true )
367 nStartCol = nEndCol;
369 } while ( bContinue );
371 else
373 while ( nStartCol > aStart.Col() &&
374 lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum )
376 --nStartCol;
378 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
381 return true;
384 bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList )
386 ScDocument* pDoc = GetViewData()->GetDocument();
387 SCTAB nTab = GetViewData()->GetTabNo();
389 SCCOL nCol = GetViewData()->GetCurX();
390 SCROW nRow = GetViewData()->GetCurY();
392 SCCOL nStartCol = nCol;
393 SCROW nStartRow = nRow;
394 SCCOL nEndCol = nCol;
395 SCROW nEndRow = nRow;
396 SCCOL nSeekCol = nCol;
397 SCROW nSeekRow = nRow;
398 SCCOLROW nExtend; // will become valid via reference for ScAutoSumSum
400 bool bCol = false;
401 bool bRow = false;
403 ScAutoSum eSum;
404 if ( nRow != 0
405 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
406 DIR_TOP, nExtend /*out*/ )) == ScAutoSumData )
407 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
408 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
411 bRow = true;
412 nSeekRow = nRow - 1;
414 else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab,
415 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
417 bCol = true;
418 nSeekCol = nCol - 1;
420 else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone )
421 bRow = true;
422 else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone )
423 bCol = true;
425 if ( bCol || bRow )
427 if ( bRow )
429 nStartRow = nSeekRow; // nSeekRow might be adjusted via reference
430 if ( eSum == ScAutoSumSum )
431 nEndRow = nStartRow; // only sum sums
432 else
433 nEndRow = nRow - 1; // maybe extend data area at bottom
435 else
437 nStartCol = nSeekCol; // nSeekCol might be adjusted vie reference
438 if ( eSum == ScAutoSumSum )
439 nEndCol = nStartCol; // only sum sums
440 else
441 nEndCol = nCol - 1; // maybe extend data area to the right
443 bool bContinue = false;
446 if ( eSum == ScAutoSumData )
448 if ( bRow )
450 while ( nStartRow != 0 && lcl_IsAutoSumData( pDoc, nCol,
451 nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum )
452 --nStartRow;
454 else
456 while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1,
457 nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum )
458 --nStartCol;
461 rRangeList.Append(
462 ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) );
463 if ( eSum == ScAutoSumSum )
465 if ( bRow )
467 nEndRow = static_cast< SCROW >( nExtend );
468 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) )
470 nStartRow = nEndRow;
473 else
475 nEndCol = static_cast< SCCOL >( nExtend );
476 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) )
478 nStartCol = nEndCol;
482 } while ( bContinue );
483 return true;
485 return false;
488 void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr)
490 OUString aFormula = GetAutoSumFormula( rRangeList, bSubTotal, rAddr );
491 EnterBlock( aFormula, NULL );
494 bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue )
496 ScDocument* pDoc = GetViewData()->GetDocument();
497 const SCTAB nTab = rRange.aStart.Tab();
498 SCCOL nStartCol = rRange.aStart.Col();
499 SCROW nStartRow = rRange.aStart.Row();
500 const SCCOL nEndCol = rRange.aEnd.Col();
501 const SCROW nEndRow = rRange.aEnd.Row();
502 SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData
504 // ignore rows at the top of the given range which don't contain autosum data
505 bool bRowData = false;
506 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
508 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
510 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone )
512 bRowData = true;
513 break;
516 if ( bRowData )
518 nStartRow = nRow;
519 break;
522 if ( !bRowData )
524 return false;
527 // ignore columns at the left of the given range which don't contain autosum data
528 bool bColData = false;
529 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
531 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
533 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone )
535 bColData = true;
536 break;
539 if ( bColData )
541 nStartCol = nCol;
542 break;
545 if ( !bColData )
547 return false;
550 const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow );
551 const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow );
552 bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) );
553 bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) );
555 // find an empty row for entering the result
556 SCROW nInsRow = nEndRow;
557 if ( bRow && !bEndRowEmpty )
559 if ( nInsRow < MAXROW )
561 ++nInsRow;
562 while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) )
564 if ( nInsRow < MAXROW )
566 ++nInsRow;
568 else
570 bRow = false;
571 break;
575 else
577 bRow = false;
581 // find an empty column for entering the result
582 SCCOL nInsCol = nEndCol;
583 if ( bCol && !bEndColEmpty )
585 if ( nInsCol < MAXCOL )
587 ++nInsCol;
588 while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) )
590 if ( nInsCol < MAXCOL )
592 ++nInsCol;
594 else
596 bCol = false;
597 break;
601 else
603 bCol = false;
607 if ( !bRow && !bCol )
609 return false;
612 SCCOL nMarkEndCol = nEndCol;
613 SCROW nMarkEndRow = nEndRow;
615 if ( bRow )
617 // calculate the row sums for all columns of the given range
619 SCROW nSumEndRow = nEndRow;
621 if ( bEndRowEmpty )
623 // the last row of the given range is empty;
624 // don't take into account for calculating the autosum
625 --nSumEndRow;
627 else
629 // increase mark range
630 ++nMarkEndRow;
633 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
635 if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) )
637 ScRangeList aRangeList;
638 const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab );
639 if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) )
641 const OUString aFormula = GetAutoSumFormula(
642 aRangeList, bSubTotal, ScAddress(nCol, nInsRow, nTab));
643 EnterData( nCol, nInsRow, nTab, aFormula );
649 if ( bCol )
651 // calculate the column sums for all rows of the given range
653 SCCOL nSumEndCol = nEndCol;
655 if ( bEndColEmpty )
657 // the last column of the given range is empty;
658 // don't take into account for calculating the autosum
659 --nSumEndCol;
661 else
663 // increase mark range
664 ++nMarkEndCol;
667 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
669 if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) )
671 ScRangeList aRangeList;
672 const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab );
673 if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) )
675 const OUString aFormula = GetAutoSumFormula( aRangeList, bSubTotal, ScAddress(nInsCol, nRow, nTab) );
676 EnterData( nInsCol, nRow, nTab, aFormula );
682 // set new mark range and cursor position
683 const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab );
684 MarkRange( aMarkRange, false, bContinue );
685 if ( bSetCursor )
687 SetCursor( nMarkEndCol, nMarkEndRow );
690 return true;
693 OUString ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr )
695 ScViewData* pViewData = GetViewData();
696 ScDocument* pDoc = pViewData->GetDocument();
697 ::boost::scoped_ptr<ScTokenArray> pArray(new ScTokenArray);
699 pArray->AddOpCode(bSubTotal ? ocSubTotal : ocSum);
700 pArray->AddOpCode(ocOpen);
702 if (bSubTotal)
704 pArray->AddDouble(9);
705 pArray->AddOpCode(ocSep);
708 if(!rRangeList.empty())
710 ScRangeList aRangeList = rRangeList;
711 const ScRange* pFirst = aRangeList.front();
712 size_t ListSize = aRangeList.size();
713 for ( size_t i = 0; i < ListSize; ++i )
715 const ScRange* p = aRangeList[i];
716 if (p != pFirst)
717 pArray->AddOpCode(ocSep);
718 ScComplexRefData aRef;
719 aRef.InitRangeRel(*p, rAddr);
720 pArray->AddDoubleReference(aRef);
724 pArray->AddOpCode(ocClose);
726 ScCompiler aComp(pDoc, rAddr, *pArray);
727 aComp.SetGrammar(pDoc->GetGrammar());
728 OUStringBuffer aBuf;
729 aComp.CreateStringFromTokenArray(aBuf);
730 OUString aFormula = aBuf.makeStringAndClear();
731 aBuf.append('=');
732 aBuf.append(aFormula);
733 return aBuf.makeStringAndClear();
736 void ScViewFunc::EnterBlock( const OUString& rString, const EditTextObject* pData )
738 // test for multi selection
740 SCCOL nCol = GetViewData()->GetCurX();
741 SCROW nRow = GetViewData()->GetCurY();
742 SCTAB nTab = GetViewData()->GetTabNo();
743 ScMarkData& rMark = GetViewData()->GetMarkData();
744 if ( rMark.IsMultiMarked() )
746 rMark.MarkToSimple();
747 if ( rMark.IsMultiMarked() )
748 { // "Insert into multi selection not possible"
749 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
751 // insert into single cell
752 if ( pData )
753 EnterData(nCol, nRow, nTab, *pData);
754 else
755 EnterData( nCol, nRow, nTab, rString );
756 return;
760 ScDocument* pDoc = GetViewData()->GetDocument();
761 OUString aNewStr = rString;
762 if ( pData )
764 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
765 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
766 aEngine.SetText(*pData);
768 ScEditAttrTester aTester( &aEngine );
769 if (!aTester.NeedsObject())
771 aNewStr = aEngine.GetText();
772 pData = NULL;
776 // Insert via PasteFromClip
778 WaitObject aWait( GetFrameWin() );
780 ScAddress aPos( nCol, nRow, nTab );
782 boost::scoped_ptr<ScDocument> pInsDoc(new ScDocument( SCDOCMODE_CLIP ));
783 pInsDoc->ResetClip( pDoc, nTab );
785 if (aNewStr[0] == '=') // Formula ?
787 // SetString not possible, because in Clipboard-Documents nothing will be compiled!
788 pInsDoc->SetFormulaCell(aPos, new ScFormulaCell(pDoc, aPos, aNewStr));
790 else if ( pData )
792 // A copy of pData will be stored.
793 pInsDoc->SetEditText(aPos, *pData, pDoc->GetEditPool());
795 else
796 pInsDoc->SetString( nCol, nRow, nTab, aNewStr );
798 pInsDoc->SetClipArea( ScRange(aPos) );
799 // insert Block, with Undo etc.
800 if ( PasteFromClip( IDF_CONTENTS, pInsDoc.get(), PASTE_NOFUNC, false, false,
801 false, INS_NONE, IDF_ATTRIB ) )
803 const SfxUInt32Item* pItem = (SfxUInt32Item*) pInsDoc->GetAttr(
804 nCol, nRow, nTab, ATTR_VALUE_FORMAT );
805 if ( pItem )
806 { // set number format if incompatible
807 // MarkData was already MarkToSimple'ed in PasteFromClip
808 ScRange aRange;
809 rMark.GetMarkArea( aRange );
810 boost::scoped_ptr<ScPatternAttr> pPattern(new ScPatternAttr( pDoc->GetPool() ));
811 pPattern->GetItemSet().Put( *pItem );
812 short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() );
813 pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark,
814 *pPattern, nNewType );
819 // manual page break
821 void ScViewFunc::InsertPageBreak( bool bColumn, bool bRecord, const ScAddress* pPos,
822 bool bSetModified )
824 SCTAB nTab = GetViewData()->GetTabNo();
825 ScAddress aCursor;
826 if (pPos)
827 aCursor = *pPos;
828 else
829 aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
831 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
832 InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, false );
834 if ( bSuccess && bSetModified )
835 UpdatePageBreakData( true ); // for PageBreak-Mode
839 void ScViewFunc::DeletePageBreak( bool bColumn, bool bRecord, const ScAddress* pPos,
840 bool bSetModified )
842 SCTAB nTab = GetViewData()->GetTabNo();
843 ScAddress aCursor;
844 if (pPos)
845 aCursor = *pPos;
846 else
847 aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
849 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
850 RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, false );
852 if ( bSuccess && bSetModified )
853 UpdatePageBreakData( true ); // for PageBreak-Mode
856 void ScViewFunc::RemoveManualBreaks()
858 ScDocShell* pDocSh = GetViewData()->GetDocShell();
859 ScDocument* pDoc = pDocSh->GetDocument();
860 SCTAB nTab = GetViewData()->GetTabNo();
861 bool bUndo(pDoc->IsUndoEnabled());
863 if (bUndo)
865 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
866 pUndoDoc->InitUndo( pDoc, nTab, nTab, true, true );
867 pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pUndoDoc );
868 pDocSh->GetUndoManager()->AddUndoAction(
869 new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) );
872 pDoc->RemoveManualBreaks(nTab);
873 pDoc->UpdatePageBreaks(nTab);
875 UpdatePageBreakData( true );
876 pDocSh->SetDocumentModified();
877 pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
880 void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages)
882 ScDocShell* pDocSh = GetViewData()->GetDocShell();
883 SCTAB nTab = GetViewData()->GetTabNo();
884 pDocSh->SetPrintZoom( nTab, nScale, nPages );
887 void ScViewFunc::AdjustPrintZoom()
889 ScRange aRange;
890 if ( GetViewData()->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
891 GetViewData()->GetMarkData().GetMultiMarkArea( aRange );
892 GetViewData()->GetDocShell()->AdjustPrintZoom( aRange );
895 void ScViewFunc::SetPrintRanges( bool bEntireSheet, const OUString* pPrint,
896 const OUString* pRepCol, const OUString* pRepRow,
897 bool bAddPrint )
899 // on all selected tables
901 ScDocShell* pDocSh = GetViewData()->GetDocShell();
902 ScDocument* pDoc = pDocSh->GetDocument();
903 ScMarkData& rMark = GetViewData()->GetMarkData();
904 SCTAB nTab;
905 bool bUndo (pDoc->IsUndoEnabled());
907 ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver();
909 ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
911 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
912 for (; itr != itrEnd; ++itr)
914 nTab = *itr;
915 ScRange aRange( 0,0,nTab );
917 // print ranges
919 if( !bAddPrint )
920 pDoc->ClearPrintRanges( nTab );
922 if( bEntireSheet )
924 pDoc->SetPrintEntireSheet( nTab );
926 else if ( pPrint )
928 if ( !pPrint->isEmpty() )
930 const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep);
931 sal_uInt16 nTCount = comphelper::string::getTokenCount(*pPrint, sep);
932 for (sal_uInt16 i=0; i<nTCount; i++)
934 OUString aToken = pPrint->getToken(i, sep);
935 if ( aRange.ParseAny( aToken, pDoc, aDetails ) & SCA_VALID )
936 pDoc->AddPrintRange( nTab, aRange );
940 else // NULL = use selection (print range is always set), use empty string to delete all ranges
942 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
944 pDoc->AddPrintRange( nTab, aRange );
946 else if ( rMark.IsMultiMarked() )
948 rMark.MarkToMulti();
949 ScRangeListRef pList( new ScRangeList );
950 rMark.FillRangeListWithMarks( pList, false );
951 for (size_t i = 0, n = pList->size(); i < n; ++i)
953 ScRange* pR = (*pList)[i];
954 pDoc->AddPrintRange(nTab, *pR);
959 // repeat columns
961 if ( pRepCol )
963 if ( pRepCol->isEmpty() )
964 pDoc->SetRepeatColRange( nTab, NULL );
965 else
966 if ( aRange.ParseAny( *pRepCol, pDoc, aDetails ) & SCA_VALID )
967 pDoc->SetRepeatColRange( nTab, &aRange );
970 // repeat rows
972 if ( pRepRow )
974 if ( pRepRow->isEmpty() )
975 pDoc->SetRepeatRowRange( nTab, NULL );
976 else
977 if ( aRange.ParseAny( *pRepRow, pDoc, aDetails ) & SCA_VALID )
978 pDoc->SetRepeatRowRange( nTab, &aRange );
982 // undo (for all tables)
983 if (bUndo)
985 SCTAB nCurTab = GetViewData()->GetTabNo();
986 ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver();
987 pDocSh->GetUndoManager()->AddUndoAction(
988 new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) );
990 else
991 delete pOldRanges;
993 // update page breaks
995 itr = rMark.begin();
996 for (; itr != itrEnd; ++itr)
997 ScPrintFunc( pDocSh, pDocSh->GetPrinter(), *itr ).UpdatePages();
999 SfxBindings& rBindings = GetViewData()->GetBindings();
1000 rBindings.Invalidate( SID_DELETE_PRINTAREA );
1002 pDocSh->SetDocumentModified();
1006 // Merge cells
1008 bool ScViewFunc::TestMergeCells() // pre-test (for menu)
1010 // simple test: true if there's a selection but no multi selection and not filtered
1012 const ScMarkData& rMark = GetViewData()->GetMarkData();
1013 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1015 ScRange aDummy;
1016 return GetViewData()->GetSimpleArea( aDummy) == SC_MARK_SIMPLE;
1018 else
1019 return false;
1023 bool ScViewFunc::MergeCells( bool bApi, bool& rDoContents, bool bRecord, bool bCenter )
1025 // Editable- and Being-Nested- test must be at the beginning (in DocFunc too),
1026 // so that the Contents-QueryBox won't appear
1027 ScEditableTester aTester( this );
1028 if (!aTester.IsEditable())
1030 ErrorMessage(aTester.GetMessageId());
1031 return false;
1034 ScMarkData& rMark = GetViewData()->GetMarkData();
1035 rMark.MarkToSimple();
1036 if (!rMark.IsMarked())
1038 ErrorMessage(STR_NOMULTISELECT);
1039 return false;
1042 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1043 ScDocument* pDoc = pDocSh->GetDocument();
1045 ScRange aMarkRange;
1046 rMark.GetMarkArea( aMarkRange );
1047 SCCOL nStartCol = aMarkRange.aStart.Col();
1048 SCROW nStartRow = aMarkRange.aStart.Row();
1049 SCTAB nStartTab = aMarkRange.aStart.Tab();
1050 SCCOL nEndCol = aMarkRange.aEnd.Col();
1051 SCROW nEndRow = aMarkRange.aEnd.Row();
1052 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1053 if ( nStartCol == nEndCol && nStartRow == nEndRow )
1055 // nothing to do
1056 return true;
1059 if ( pDoc->HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1060 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1061 { // "Don't nest merging !"
1062 ErrorMessage(STR_MSSG_MERGECELLS_0);
1063 return false;
1066 // Check for the contents of all selected tables.
1067 bool bAskDialog = false;
1068 ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter);
1069 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1070 for (; itr != itrEnd; ++itr)
1072 SCTAB i = *itr;
1073 aMergeOption.maTabs.insert(i);
1075 if (!pDoc->IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) ||
1076 !pDoc->IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow))
1077 bAskDialog = true;
1080 bool bOk = true;
1082 if (bAskDialog)
1084 if (!bApi)
1086 MessBox aBox( GetViewData()->GetDialogParent(),
1087 WinBits(WB_YES_NO_CANCEL | WB_DEF_NO),
1088 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
1089 ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) );
1090 sal_uInt16 nRetVal = aBox.Execute();
1092 if ( nRetVal == RET_YES )
1093 rDoContents = true;
1094 else if ( nRetVal == RET_CANCEL )
1095 bOk = false;
1099 if (bOk)
1101 bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi );
1103 if (bOk)
1105 SetCursor( nStartCol, nStartRow );
1106 //DoneBlockMode( sal_False);
1107 Unmark();
1109 pDocSh->UpdateOle(GetViewData());
1110 UpdateInputLine();
1114 return bOk;
1118 bool ScViewFunc::TestRemoveMerge()
1120 bool bMerged = false;
1121 ScRange aRange;
1122 if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1124 ScDocument* pDoc = GetViewData()->GetDocument();
1125 if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
1126 bMerged = true;
1128 return bMerged;
1132 static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange)
1134 bool bExtended = false;
1135 if (rOption.mnStartCol > rRange.aStart.Col())
1137 rOption.mnStartCol = rRange.aStart.Col();
1138 bExtended = true;
1140 if (rOption.mnStartRow > rRange.aStart.Row())
1142 rOption.mnStartRow = rRange.aStart.Row();
1143 bExtended = true;
1145 if (rOption.mnEndCol < rRange.aEnd.Col())
1147 rOption.mnEndCol = rRange.aEnd.Col();
1148 bExtended = true;
1150 if (rOption.mnEndRow < rRange.aEnd.Row())
1152 rOption.mnEndRow = rRange.aEnd.Row();
1153 bExtended = true;
1155 return bExtended;
1158 bool ScViewFunc::RemoveMerge( bool bRecord )
1160 ScRange aRange;
1161 ScEditableTester aTester( this );
1162 if (!aTester.IsEditable())
1164 ErrorMessage(aTester.GetMessageId());
1165 return false;
1167 else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1169 ScDocument* pDoc = GetViewData()->GetDocument();
1170 ScRange aExtended( aRange );
1171 pDoc->ExtendMerge( aExtended );
1172 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1173 const ScMarkData& rMark = GetViewData()->GetMarkData();
1174 ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row());
1175 bool bExtended = false;
1178 bExtended = false;
1179 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1180 for (; itr != itrEnd; ++itr)
1182 SCTAB i = *itr;
1183 aOption.maTabs.insert(i);
1184 aExtended.aStart.SetTab(i);
1185 aExtended.aEnd.SetTab(i);
1186 pDoc->ExtendMerge(aExtended);
1187 pDoc->ExtendOverlapped(aExtended);
1189 // Expand the current range to be inclusive of all merged
1190 // areas on all sheets.
1191 bExtended = lcl_extendMergeRange(aOption, aExtended);
1194 while (bExtended);
1196 bool bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord );
1197 aExtended = aOption.getFirstSingleRange();
1198 MarkRange( aExtended );
1200 if (bOk)
1201 pDocSh->UpdateOle(GetViewData());
1203 return true; //! bOk ??
1206 void ScViewFunc::FillSimple( FillDir eDir, bool bRecord )
1208 ScRange aRange;
1209 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1211 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1212 const ScMarkData& rMark = GetViewData()->GetMarkData();
1213 bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, false );
1214 if (bSuccess)
1216 pDocSh->UpdateOle(GetViewData());
1217 UpdateScrollBars();
1220 else
1221 ErrorMessage(STR_NOMULTISELECT);
1224 void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
1225 double fStart, double fStep, double fMax, bool bRecord )
1227 ScRange aRange;
1228 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1230 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1231 const ScMarkData& rMark = GetViewData()->GetMarkData();
1232 bool bSuccess = pDocSh->GetDocFunc().
1233 FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd,
1234 fStart, fStep, fMax, bRecord, false );
1235 if (bSuccess)
1237 pDocSh->UpdateOle(GetViewData());
1238 UpdateScrollBars();
1240 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange);
1243 else
1244 ErrorMessage(STR_NOMULTISELECT);
1247 void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
1248 SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, bool bRecord )
1250 SCTAB nTab = GetViewData()->GetTabNo();
1251 ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab );
1252 ScRange aSourceRange( aRange );
1253 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1254 const ScMarkData& rMark = GetViewData()->GetMarkData();
1255 bool bSuccess = pDocSh->GetDocFunc().
1256 FillAuto( aRange, &rMark, eDir, nCount, bRecord, false );
1257 if (bSuccess)
1259 MarkRange( aRange, false ); // aRange was modified in FillAuto
1260 pDocSh->UpdateOle(GetViewData());
1261 UpdateScrollBars();
1263 if (ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
1265 ScRangeList aChangeRanges;
1266 ScRange aChangeRange( aRange );
1267 switch (eDir)
1269 case FILL_TO_BOTTOM:
1270 aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 );
1271 break;
1272 case FILL_TO_TOP:
1273 aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 );
1274 break;
1275 case FILL_TO_RIGHT:
1276 aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 );
1277 break;
1278 case FILL_TO_LEFT:
1279 aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 );
1280 break;
1281 default:
1282 break;
1284 aChangeRanges.Append( aChangeRange );
1285 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1290 void ScViewFunc::FillTab( sal_uInt16 nFlags, sal_uInt16 nFunction, bool bSkipEmpty, bool bAsLink )
1292 //! allow source sheet to be protected
1293 ScEditableTester aTester( this );
1294 if (!aTester.IsEditable())
1296 ErrorMessage(aTester.GetMessageId());
1297 return;
1300 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1301 ScDocument* pDoc = pDocSh->GetDocument();
1302 ScMarkData& rMark = GetViewData()->GetMarkData();
1303 SCTAB nTab = GetViewData()->GetTabNo();
1304 bool bUndo(pDoc->IsUndoEnabled());
1306 ScRange aMarkRange;
1307 rMark.MarkToSimple();
1308 bool bMulti = rMark.IsMultiMarked();
1309 if (bMulti)
1310 rMark.GetMultiMarkArea( aMarkRange );
1311 else if (rMark.IsMarked())
1312 rMark.GetMarkArea( aMarkRange );
1313 else
1314 aMarkRange = ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
1316 ScDocument* pUndoDoc = NULL;
1318 if (bUndo)
1320 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1321 pUndoDoc->InitUndo( pDoc, nTab, nTab );
1323 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1324 for (; itr != itrEnd; ++itr)
1325 if (*itr != nTab )
1327 SCTAB i = *itr;
1328 pUndoDoc->AddUndoTab( i, i );
1329 aMarkRange.aStart.SetTab( i );
1330 aMarkRange.aEnd.SetTab( i );
1331 pDoc->CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc );
1335 if (bMulti)
1336 pDoc->FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1337 else
1339 aMarkRange.aStart.SetTab( nTab );
1340 aMarkRange.aEnd.SetTab( nTab );
1341 pDoc->FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1344 if (bUndo)
1345 { //! for ChangeTrack not until the end
1346 pDocSh->GetUndoManager()->AddUndoAction(
1347 new ScUndoFillTable( pDocSh, rMark,
1348 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab,
1349 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab,
1350 pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) );
1353 pDocSh->PostPaintGridAll();
1354 pDocSh->PostDataChanged();
1357 /** Downward fill of selected cell(s) by double-clicking cross-hair cursor
1359 Extends a current selection down to the last non-empty cell of an adjacent
1360 column when the lower-right corner of the selection is double-clicked. It
1361 uses a left-adjoining non-empty column as a guide if such is available,
1362 otherwise a right-adjoining non-empty column is used.
1364 @author Kohei Yoshida (kohei@openoffice.org)
1366 @return No return value
1368 @see #i12313#
1370 void ScViewFunc::FillCrossDblClick()
1372 ScRange aRange;
1373 GetViewData()->GetSimpleArea( aRange );
1374 aRange.Justify();
1376 SCTAB nTab = GetViewData()->GetCurPos().Tab();
1377 SCCOL nStartX = aRange.aStart.Col();
1378 SCROW nStartY = aRange.aStart.Row();
1379 SCCOL nEndX = aRange.aEnd.Col();
1380 SCROW nEndY = aRange.aEnd.Row();
1382 ScDocument* pDoc = GetViewData()->GetDocument();
1384 // Make sure the selection is not empty
1385 if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) )
1386 return;
1388 if ( nEndY < MAXROW )
1390 if ( nStartX > 0 )
1392 SCCOL nMovX = nStartX - 1;
1393 SCROW nMovY = nStartY;
1395 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1396 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1398 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1400 if ( nMovY > nEndY )
1402 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1403 nMovY - nEndY );
1404 return;
1409 if ( nEndX < MAXCOL )
1411 SCCOL nMovX = nEndX + 1;
1412 SCROW nMovY = nStartY;
1414 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1415 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1417 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1419 if ( nMovY > nEndY )
1421 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1422 nMovY - nEndY );
1423 return;
1430 void ScViewFunc::TransliterateText( sal_Int32 nType )
1432 ScMarkData aFuncMark = GetViewData()->GetMarkData();
1433 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1435 // no selection -> use cursor position
1437 ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1438 aFuncMark.SetMarkArea( ScRange( aCursor ) );
1441 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
1442 TransliterateText( aFuncMark, nType, true, false );
1443 if (bSuccess)
1445 GetViewData()->GetViewShell()->UpdateInputHandler();
1450 // AutoFormat
1452 ScAutoFormatData* ScViewFunc::CreateAutoFormatData()
1454 ScAutoFormatData* pData = NULL;
1455 SCCOL nStartCol;
1456 SCROW nStartRow;
1457 SCTAB nStartTab;
1458 SCCOL nEndCol;
1459 SCROW nEndRow;
1460 SCTAB nEndTab;
1461 if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1463 if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 )
1465 ScDocument* pDoc = GetViewData()->GetDocument();
1466 pData = new ScAutoFormatData;
1467 pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData );
1470 return pData;
1474 void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, bool bRecord )
1476 ScRange aRange;
1477 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1479 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1480 ScMarkData& rMark = GetViewData()->GetMarkData();
1482 bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, false );
1483 if (bSuccess)
1484 pDocSh->UpdateOle(GetViewData());
1486 else
1487 ErrorMessage(STR_NOMULTISELECT);
1490 // Suchen & Ersetzen
1492 bool ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem,
1493 bool bAddUndo, bool bIsApi )
1495 SvxSearchDialogWrapper::SetSearchLabel(SL_Empty);
1496 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1497 ScDocument* pDoc = pDocSh->GetDocument();
1498 ScMarkData& rMark = GetViewData()->GetMarkData();
1499 if (bAddUndo && !pDoc->IsUndoEnabled())
1500 bAddUndo = false;
1502 SCCOL nCol, nOldCol;
1503 SCROW nRow, nOldRow;
1504 SCTAB nTab, nOldTab;
1505 nCol = nOldCol = GetViewData()->GetCurX();
1506 nRow = nOldRow = GetViewData()->GetCurY();
1507 nTab = nOldTab = GetViewData()->GetTabNo();
1509 sal_uInt16 nCommand = pSearchItem->GetCommand();
1510 bool bAllTables = pSearchItem->IsAllTables();
1511 std::set<SCTAB> aOldSelectedTables;
1512 SCTAB nLastTab = pDoc->GetTableCount() - 1;
1513 SCTAB nStartTab, nEndTab;
1514 if ( bAllTables )
1516 nStartTab = 0;
1517 nEndTab = nLastTab;
1518 std::set<SCTAB> aTmp(rMark.begin(), rMark.end());
1519 aOldSelectedTables.swap(aTmp);
1521 else
1522 { //! at least one is always selected
1523 nStartTab = rMark.GetFirstSelected();
1524 nEndTab = rMark.GetLastSelected();
1527 if ( nCommand == SVX_SEARCHCMD_FIND
1528 || nCommand == SVX_SEARCHCMD_FIND_ALL)
1529 bAddUndo = false;
1531 //! account for bAttrib during Undo !!!
1533 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1534 std::auto_ptr<ScDocument> pUndoDoc;
1535 std::auto_ptr<ScMarkData> pUndoMark;
1536 SAL_WNODEPRECATED_DECLARATIONS_POP
1537 OUString aUndoStr;
1538 if (bAddUndo)
1540 pUndoMark.reset(new ScMarkData(rMark)); // Mark is being modified
1541 if ( nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1543 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1544 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
1548 if ( bAllTables )
1549 { //! select all, after pUndoMark has been created
1550 for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1552 rMark.SelectTable( j, true );
1556 DoneBlockMode(true); // don't delete mark
1557 InitOwnBlockMode();
1559 // If search starts at the beginning don't ask again whether it shall start at the beginning
1560 bool bFirst = true;
1561 if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() )
1562 bFirst = false;
1564 bool bFound = false;
1565 while (true)
1567 GetFrameWin()->EnterWait();
1568 ScRangeList aMatchedRanges;
1569 if (pDoc->SearchAndReplace(*pSearchItem, nCol, nRow, nTab, rMark, aMatchedRanges, aUndoStr, pUndoDoc.get()))
1571 bFound = true;
1572 bFirst = true;
1573 if (bAddUndo)
1575 GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction(
1576 new ScUndoReplace( GetViewData()->GetDocShell(), *pUndoMark,
1577 nCol, nRow, nTab,
1578 aUndoStr, pUndoDoc.release(), pSearchItem ) );
1581 if (nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL)
1583 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1584 if (pViewFrm)
1586 pViewFrm->ShowChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId(), true);
1587 SfxChildWindow* pWnd = pViewFrm->GetChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId());
1588 if (pWnd)
1590 sc::SearchResultsDlg* pDlg = static_cast<sc::SearchResultsDlg*>(pWnd->GetWindow());
1591 if (pDlg)
1592 pDlg->FillResults(pDoc, aMatchedRanges);
1596 rMark.ResetMark();
1597 for (size_t i = 0, n = aMatchedRanges.size(); i < n; ++i)
1599 const ScRange& r = *aMatchedRanges[i];
1600 if (r.aStart.Tab() == nTab)
1601 rMark.SetMultiMarkArea(r);
1605 break; // break 'while (TRUE)'
1607 else if ( bFirst && (nCommand == SVX_SEARCHCMD_FIND ||
1608 nCommand == SVX_SEARCHCMD_REPLACE) )
1610 bFirst = false;
1611 GetFrameWin()->LeaveWait();
1612 if (!bIsApi)
1614 if ( nStartTab == nEndTab )
1615 SvxSearchDialogWrapper::SetSearchLabel(SL_EndSheet);
1616 else
1617 SvxSearchDialogWrapper::SetSearchLabel(SL_End);
1619 ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
1620 if (pSearchItem->GetBackward())
1621 nTab = nEndTab;
1622 else
1623 nTab = nStartTab;
1625 else
1627 break; // break 'while (TRUE)'
1630 else // nothing found
1632 if ( nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1634 pDocSh->PostPaintGridAll(); // Mark
1637 GetFrameWin()->LeaveWait();
1638 if (!bIsApi)
1639 SvxSearchDialogWrapper::SetSearchLabel(SL_NotFound);
1641 break; // break 'while (TRUE)'
1643 } // of while true
1645 if (!aOldSelectedTables.empty())
1647 // restore originally selected table
1648 for (SCTAB i = 0; i <= nEndTab; ++i)
1649 rMark.SelectTable(i, false);
1651 std::set<SCTAB>::const_iterator itr = aOldSelectedTables.begin(), itrEnd = aOldSelectedTables.end();
1652 for (; itr != itrEnd; ++itr)
1653 rMark.SelectTable(*itr, true);
1655 if ( bFound )
1656 { // if a table is selected as a "match" it remains selected.
1657 rMark.SelectTable( nTab, true );
1658 // It's a swap if only one table was selected before
1659 //! otherwise now one table more might be selected
1660 if ( aOldSelectedTables.size() == 1 && nTab != nOldTab )
1661 rMark.SelectTable( nOldTab, false );
1665 MarkDataChanged();
1667 if ( bFound )
1669 if ( nTab != GetViewData()->GetTabNo() )
1670 SetTabNo( nTab );
1672 // if nothing is marked, DoneBlockMode, then marking can start
1673 // directly from this place via Shift-Cursor
1674 if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1675 DoneBlockMode(true);
1677 AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
1678 SetCursor( nCol, nRow, true );
1680 if ( nCommand == SVX_SEARCHCMD_REPLACE
1681 || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1683 if ( nCommand == SVX_SEARCHCMD_REPLACE )
1685 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID );
1687 // jump to next cell if we replaced everything in the cell
1688 // where the cursor was positioned (but avoid switching tabs)
1689 if ( nCol == nOldCol && nRow == nOldRow && nTab == nOldTab )
1691 SvxSearchItem aSearchItem = ScGlobal::GetSearchItem();
1692 aSearchItem.SetCommand(SVX_SEARCHCMD_FIND);
1693 aSearchItem.SetWhich(SID_SEARCH_ITEM);
1695 ScRangeList aMatchedRanges;
1696 ScTable::UpdateSearchItemAddressForReplace( aSearchItem, nCol, nRow );
1697 if ( pDoc->SearchAndReplace( aSearchItem, nCol, nRow, nTab, rMark, aMatchedRanges, aUndoStr, NULL ) &&
1698 ( nTab == nOldTab ) &&
1699 ( nCol != nOldCol || nRow != nOldRow ) )
1701 SetCursor( nCol, nRow, true );
1705 else
1706 pDocSh->PostPaintGridAll();
1707 pDocSh->SetDocumentModified();
1709 else if ( nCommand == SVX_SEARCHCMD_FIND_ALL )
1710 pDocSh->PostPaintGridAll(); // mark
1711 GetFrameWin()->LeaveWait();
1713 return bFound;
1716 // Zielwertsuche
1718 void ScViewFunc::Solve( const ScSolveParam& rParam )
1720 ScDocument* pDoc = GetViewData()->GetDocument();
1722 SCCOL nDestCol = rParam.aRefVariableCell.Col();
1723 SCROW nDestRow = rParam.aRefVariableCell.Row();
1724 SCTAB nDestTab = rParam.aRefVariableCell.Tab();
1726 ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow );
1727 if (!aTester.IsEditable())
1729 ErrorMessage(aTester.GetMessageId());
1730 return;
1733 if ( pDoc )
1735 OUString aTargetValStr;
1736 if ( rParam.pStrTargetVal != NULL )
1737 aTargetValStr = *(rParam.pStrTargetVal);
1739 OUString aMsgStr;
1740 OUString aResStr;
1741 double nSolveResult;
1743 GetFrameWin()->EnterWait();
1745 bool bExact =
1746 pDoc->Solver(
1747 rParam.aRefFormulaCell.Col(),
1748 rParam.aRefFormulaCell.Row(),
1749 rParam.aRefFormulaCell.Tab(),
1750 nDestCol, nDestRow, nDestTab,
1751 aTargetValStr,
1752 nSolveResult );
1754 GetFrameWin()->LeaveWait();
1756 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1757 sal_uLong nFormat = 0;
1758 const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab );
1759 if ( pPattern )
1760 nFormat = pPattern->GetNumberFormat( pFormatter );
1761 Color* p;
1762 pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p );
1764 if ( bExact )
1766 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_0 );
1767 aMsgStr += aResStr;
1768 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 );
1770 else
1772 aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_2 );
1773 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_3 );
1774 aMsgStr += aResStr ;
1775 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 );
1778 MessBox aBox( GetViewData()->GetDialogParent(),
1779 WinBits(WB_YES_NO | WB_DEF_NO),
1780 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr );
1781 sal_uInt16 nRetVal = aBox.Execute();
1783 if ( RET_YES == nRetVal )
1784 EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult );
1786 GetViewData()->GetViewShell()->UpdateInputHandler( true );
1790 // multi operation
1792 void ScViewFunc::TabOp( const ScTabOpParam& rParam, bool bRecord )
1794 ScRange aRange;
1795 if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1797 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1798 ScMarkData& rMark = GetViewData()->GetMarkData();
1799 pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, false );
1801 else
1802 ErrorMessage(STR_NOMULTISELECT);
1806 void ScViewFunc::MakeScenario( const OUString& rName, const OUString& rComment,
1807 const Color& rColor, sal_uInt16 nFlags )
1809 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1810 ScMarkData& rMark = GetViewData()->GetMarkData();
1811 SCTAB nTab = GetViewData()->GetTabNo();
1813 SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark );
1814 if (nFlags & SC_SCENARIO_COPYALL)
1815 SetTabNo( nNewTab, true ); // SC_SCENARIO_COPYALL -> visible
1816 else
1818 SfxBindings& rBindings = GetViewData()->GetBindings();
1819 rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar
1820 rBindings.Invalidate( SID_ROWCOL_SELCOUNT ); // Statusbar
1821 rBindings.Invalidate( SID_TABLES_COUNT );
1822 rBindings.Invalidate( SID_SELECT_SCENARIO );
1823 rBindings.Invalidate( FID_TABLE_SHOW );
1828 void ScViewFunc::ExtendScenario()
1830 ScEditableTester aTester( this );
1831 if (!aTester.IsEditable())
1833 ErrorMessage(aTester.GetMessageId());
1834 return;
1837 // Undo: apply attributes
1839 ScDocument* pDoc = GetViewData()->GetDocument();
1840 ScPatternAttr aPattern( pDoc->GetPool() );
1841 aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
1842 aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
1843 ApplySelectionPattern(aPattern);
1847 void ScViewFunc::UseScenario( const OUString& rName )
1849 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1850 SCTAB nTab = GetViewData()->GetTabNo();
1852 DoneBlockMode();
1853 InitOwnBlockMode();
1854 pDocSh->UseScenario( nTab, rName );
1857 // Insert table
1859 bool ScViewFunc::InsertTable( const OUString& rName, SCTAB nTab, bool bRecord )
1861 // Order Tabl/Name is inverted for DocFunc
1862 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
1863 InsertTable( nTab, rName, bRecord, false );
1864 if (bSuccess)
1865 SetTabNo( nTab, true );
1867 return bSuccess;
1871 // Insert tables
1873 bool ScViewFunc::InsertTables(std::vector<OUString>& aNames, SCTAB nTab,
1874 SCTAB nCount, bool bRecord )
1876 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1877 ScDocument* pDoc = pDocSh->GetDocument();
1878 if (bRecord && !pDoc->IsUndoEnabled())
1879 bRecord = false;
1881 WaitObject aWait( GetFrameWin() );
1883 if (bRecord)
1885 pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
1888 bool bFlag=false;
1890 if(aNames.empty())
1892 pDoc->CreateValidTabNames(aNames, nCount);
1894 if (pDoc->InsertTabs(nTab, aNames, false))
1896 pDocSh->Broadcast( ScTablesHint( SC_TABS_INSERTED, nTab, nCount ) );
1897 bFlag = true;
1900 if (bFlag)
1902 if (bRecord)
1903 pDocSh->GetUndoManager()->AddUndoAction(
1904 new ScUndoInsertTables( pDocSh, nTab, aNames));
1906 // Update views
1908 SetTabNo( nTab, true );
1909 pDocSh->PostPaintExtras();
1910 pDocSh->SetDocumentModified();
1911 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
1912 return true;
1914 else
1916 return false;
1921 bool ScViewFunc::AppendTable( const OUString& rName, bool bRecord )
1923 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1924 ScDocument* pDoc = pDocSh->GetDocument();
1925 if (bRecord && !pDoc->IsUndoEnabled())
1926 bRecord = false;
1928 WaitObject aWait( GetFrameWin() );
1930 if (bRecord)
1931 pDoc->BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
1933 if (pDoc->InsertTab( SC_TAB_APPEND, rName ))
1935 SCTAB nTab = pDoc->GetTableCount()-1;
1936 if (bRecord)
1937 pDocSh->GetUndoManager()->AddUndoAction(
1938 new ScUndoInsertTab( pDocSh, nTab, true, rName));
1939 GetViewData()->InsertTab( nTab );
1940 SetTabNo( nTab, true );
1941 pDocSh->PostPaintExtras();
1942 pDocSh->SetDocumentModified();
1943 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
1944 return true;
1946 else
1948 return false;
1953 bool ScViewFunc::DeleteTable( SCTAB nTab, bool bRecord )
1955 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1956 ScDocument* pDoc = pDocSh->GetDocument();
1958 bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, false );
1959 if (bSuccess)
1961 SCTAB nNewTab = nTab;
1962 if ( nNewTab >= pDoc->GetTableCount() )
1963 --nNewTab;
1964 SetTabNo( nNewTab, true );
1966 return bSuccess;
1969 //only use this method for undo for now, all sheets must be connected
1970 //this method doesn't support undo for now, merge it when it with the other method later
1971 bool ScViewFunc::DeleteTables( const SCTAB nTab, SCTAB nSheets )
1973 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1974 ScDocument* pDoc = pDocSh->GetDocument();
1975 bool bVbaEnabled = pDoc->IsInVBAMode();
1976 SCTAB nNewTab = nTab;
1977 WaitObject aWait( GetFrameWin() );
1979 while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) )
1980 --nNewTab;
1982 if (pDoc->DeleteTabs(nTab, nSheets))
1984 if( bVbaEnabled )
1986 for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
1988 OUString sCodeName;
1989 bool bHasCodeName = pDoc->GetCodeName( nTab + aTab, sCodeName );
1990 if ( bHasCodeName )
1991 VBA_DeleteModule( *pDocSh, sCodeName );
1995 pDocSh->Broadcast( ScTablesHint( SC_TABS_DELETED, nTab, nSheets ) );
1996 if ( nNewTab >= pDoc->GetTableCount() )
1997 nNewTab = pDoc->GetTableCount() - 1;
1998 SetTabNo( nNewTab, true );
2000 pDocSh->PostPaintExtras();
2001 pDocSh->SetDocumentModified();
2003 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2004 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2005 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2006 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2007 return true;
2009 return false;
2012 bool ScViewFunc::DeleteTables(const vector<SCTAB> &TheTabs, bool bRecord )
2014 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2015 ScDocument* pDoc = pDocSh->GetDocument();
2016 bool bVbaEnabled = pDoc->IsInVBAMode();
2017 SCTAB nNewTab = TheTabs.front();
2018 WaitObject aWait( GetFrameWin() );
2019 if (bRecord && !pDoc->IsUndoEnabled())
2020 bRecord = false;
2021 if ( bVbaEnabled )
2022 bRecord = false;
2024 while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) )
2025 --nNewTab;
2027 bool bWasLinked = false;
2028 ScDocument* pUndoDoc = NULL;
2029 ScRefUndoData* pUndoData = NULL;
2030 if (bRecord)
2032 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2033 SCTAB nCount = pDoc->GetTableCount();
2035 OUString aOldName;
2036 for(unsigned int i=0; i<TheTabs.size(); ++i)
2038 SCTAB nTab = TheTabs[i];
2039 if (i==0)
2040 pUndoDoc->InitUndo( pDoc, nTab,nTab, true,true ); // incl. column/fow flags
2041 else
2042 pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/fow flags
2044 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
2045 pDoc->GetName( nTab, aOldName );
2046 pUndoDoc->RenameTab( nTab, aOldName, false );
2047 if (pDoc->IsLinked(nTab))
2049 bWasLinked = true;
2050 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2051 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2052 pDoc->GetLinkTab(nTab),
2053 pDoc->GetLinkRefreshDelay(nTab) );
2055 if ( pDoc->IsScenario(nTab) )
2057 pUndoDoc->SetScenario( nTab, true );
2058 OUString aComment;
2059 Color aColor;
2060 sal_uInt16 nScenFlags;
2061 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2062 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2063 bool bActive = pDoc->IsActiveScenario( nTab );
2064 pUndoDoc->SetActiveScenario( nTab, bActive );
2066 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2067 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
2068 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
2069 pUndoDoc->SetLayoutRTL( nTab, pDoc->IsLayoutRTL( nTab ) );
2071 if ( pDoc->IsTabProtected( nTab ) )
2072 pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab));
2074 // Drawing-Layer is responsible for its Undo !!!
2075 // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
2078 pUndoDoc->AddUndoTab( 0, nCount-1 ); // all Tabs for references
2080 pDoc->BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage
2082 pUndoData = new ScRefUndoData( pDoc );
2085 bool bDelDone = false;
2087 for(int i=TheTabs.size()-1; i>=0; --i)
2089 OUString sCodeName;
2090 bool bHasCodeName = pDoc->GetCodeName( TheTabs[i], sCodeName );
2091 if (pDoc->DeleteTab(TheTabs[i]))
2093 bDelDone = true;
2094 if( bVbaEnabled )
2096 if( bHasCodeName )
2098 VBA_DeleteModule( *pDocSh, sCodeName );
2101 pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i] ) );
2104 if (bRecord)
2106 pDocSh->GetUndoManager()->AddUndoAction(
2107 new ScUndoDeleteTab( GetViewData()->GetDocShell(), TheTabs,
2108 pUndoDoc, pUndoData ));
2112 if (bDelDone)
2114 if ( nNewTab >= pDoc->GetTableCount() )
2115 nNewTab = pDoc->GetTableCount() - 1;
2117 SetTabNo( nNewTab, true );
2119 if (bWasLinked)
2121 pDocSh->UpdateLinks(); // update Link-Manager
2122 GetViewData()->GetBindings().Invalidate(SID_LINKS);
2125 pDocSh->PostPaintExtras();
2126 pDocSh->SetDocumentModified();
2129 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2130 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2131 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2132 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2134 else
2136 delete pUndoDoc;
2137 delete pUndoData;
2139 return bDelDone;
2143 bool ScViewFunc::RenameTable( const OUString& rName, SCTAB nTab )
2145 // order Table/Name is inverted for DocFunc
2146 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
2147 RenameTable( nTab, rName, true, false );
2148 if (bSuccess)
2150 // the table name might be part of a formula
2151 GetViewData()->GetViewShell()->UpdateInputHandler();
2153 return bSuccess;
2157 bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab )
2159 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, true, false );
2160 if (bSuccess)
2162 GetViewData()->GetViewShell()->UpdateInputHandler();
2164 return bSuccess;
2167 bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList )
2169 bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, true, false );
2170 if (bSuccess)
2172 GetViewData()->GetViewShell()->UpdateInputHandler();
2174 return bSuccess;
2177 void ScViewFunc::InsertAreaLink( const OUString& rFile,
2178 const OUString& rFilter, const OUString& rOptions,
2179 const OUString& rSource, sal_uLong nRefresh )
2181 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2182 SCCOL nPosX = GetViewData()->GetCurX();
2183 SCROW nPosY = GetViewData()->GetCurY();
2184 SCTAB nTab = GetViewData()->GetTabNo();
2185 ScAddress aPos( nPosX, nPosY, nTab );
2187 pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, false, false );
2191 void ScViewFunc::InsertTableLink( const OUString& rFile,
2192 const OUString& rFilter, const OUString& rOptions,
2193 const OUString& rTabName )
2195 OUString aFilterName = rFilter;
2196 OUString aOpt = rOptions;
2197 OUString aURL = rFile;
2198 ScDocumentLoader aLoader( aURL, aFilterName, aOpt );
2199 if (!aLoader.IsError())
2201 ScDocShell* pSrcSh = aLoader.GetDocShell();
2202 ScDocument* pSrcDoc = pSrcSh->GetDocument();
2203 SCTAB nTab = MAXTAB+1;
2204 if (rTabName.isEmpty()) // no name given -> first table
2205 nTab = 0;
2206 else
2208 OUString aTemp;
2209 SCTAB nCount = pSrcDoc->GetTableCount();
2210 for (SCTAB i=0; i<nCount; i++)
2212 pSrcDoc->GetName( i, aTemp );
2213 if ( aTemp.equals(rTabName) )
2214 nTab = i;
2218 if ( nTab <= MAXTAB )
2219 ImportTables( pSrcSh, 1, &nTab, true,
2220 GetViewData()->GetTabNo() );
2224 // Copy/link tables from another document
2226 void ScViewFunc::ImportTables( ScDocShell* pSrcShell,
2227 SCTAB nCount, const SCTAB* pSrcTabs, bool bLink,SCTAB nTab )
2229 ScDocument* pSrcDoc = pSrcShell->GetDocument();
2231 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2232 ScDocument* pDoc = pDocSh->GetDocument();
2233 bool bUndo(pDoc->IsUndoEnabled());
2235 bool bError = false;
2236 bool bRefs = false;
2237 bool bName = false;
2239 if (pSrcDoc->GetDrawLayer())
2240 pDocSh->MakeDrawLayer();
2242 if (bUndo)
2243 pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2245 SCTAB nInsCount = 0;
2246 SCTAB i;
2247 for( i=0; i<nCount; i++ )
2248 { // insert sheets first and update all references
2249 OUString aName;
2250 pSrcDoc->GetName( pSrcTabs[i], aName );
2251 pDoc->CreateValidTabName( aName );
2252 if ( !pDoc->InsertTab( nTab+i, aName ) )
2254 bError = true; // total error
2255 break; // for
2257 ++nInsCount;
2259 for (i=0; i<nCount && !bError; i++)
2261 SCTAB nSrcTab = pSrcTabs[i];
2262 SCTAB nDestTab1=nTab+i;
2263 sal_uLong nErrVal = pDocSh->TransferTab( *pSrcShell, nSrcTab, nDestTab1,
2264 false, false ); // no insert
2266 switch (nErrVal)
2268 case 0: // internal error or full of errors
2269 bError = true;
2270 break;
2271 case 2:
2272 bRefs = true;
2273 break;
2274 case 3:
2275 bName = true;
2276 break;
2277 case 4:
2278 bRefs = bName = true;
2279 break;
2284 if (bLink)
2286 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
2288 SfxMedium* pMed = pSrcShell->GetMedium();
2289 OUString aFileName = pMed->GetName();
2290 OUString aFilterName;
2291 if (pMed->GetFilter())
2292 aFilterName = pMed->GetFilter()->GetFilterName();
2293 OUString aOptions = ScDocumentLoader::GetOptions(*pMed);
2295 bool bWasThere = pDoc->HasLink( aFileName, aFilterName, aOptions );
2297 sal_uLong nRefresh = 0;
2298 OUString aTabStr;
2299 for (i=0; i<nInsCount; i++)
2301 pSrcDoc->GetName( pSrcTabs[i], aTabStr );
2302 pDoc->SetLink( nTab+i, SC_LINK_NORMAL,
2303 aFileName, aFilterName, aOptions, aTabStr, nRefresh );
2306 if (!bWasThere) // Insert link only once per source document
2308 ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh );
2309 pLink->SetInCreate( true );
2310 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName );
2311 pLink->Update();
2312 pLink->SetInCreate( false );
2314 SfxBindings& rBindings = GetViewData()->GetBindings();
2315 rBindings.Invalidate( SID_LINKS );
2320 if (bUndo)
2322 pDocSh->GetUndoManager()->AddUndoAction(
2323 new ScUndoImportTab( pDocSh, nTab, nCount ) );
2326 for (i=0; i<nInsCount; i++)
2327 GetViewData()->InsertTab(nTab);
2328 SetTabNo(nTab,true);
2329 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2330 PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
2332 SfxApplication* pSfxApp = SFX_APP();
2333 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2334 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2336 pDocSh->PostPaintExtras();
2337 pDocSh->PostPaintGridAll();
2338 pDocSh->SetDocumentModified();
2340 if (bRefs)
2341 ErrorMessage(STR_ABSREFLOST);
2342 if (bName)
2343 ErrorMessage(STR_NAMECONFLICT);
2346 // Move/Copy table to another document
2348 void ScViewFunc::MoveTable(
2349 sal_uInt16 nDestDocNo, SCTAB nDestTab, bool bCopy, const OUString* pNewTabName )
2351 ScDocument* pDoc = GetViewData()->GetDocument();
2352 ScDocShell* pDocShell = GetViewData()->GetDocShell();
2353 ScDocument* pDestDoc = NULL;
2354 ScDocShell* pDestShell = NULL;
2355 ScTabViewShell* pDestViewSh = NULL;
2356 bool bUndo (pDoc->IsUndoEnabled());
2357 bool bRename = pNewTabName && !pNewTabName->isEmpty();
2359 bool bNewDoc = (nDestDocNo == SC_DOC_NEW);
2360 if ( bNewDoc )
2362 nDestTab = 0; // firstly insert
2364 // execute without SFX_CALLMODE_RECORD, because already contained in move command
2366 OUString aUrl("private:factory/" STRING_SCAPP);
2367 SfxStringItem aItem( SID_FILE_NAME, aUrl );
2368 SfxStringItem aTarget( SID_TARGETNAME, OUString("_blank") );
2370 const SfxPoolItem* pRetItem = GetViewData()->GetDispatcher().Execute(
2371 SID_OPENDOC, SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON, &aItem, &aTarget, 0L );
2372 if ( pRetItem )
2374 if ( pRetItem->ISA( SfxObjectItem ) )
2375 pDestShell = PTR_CAST( ScDocShell, ((const SfxObjectItem*)pRetItem)->GetShell() );
2376 else if ( pRetItem->ISA( SfxViewFrameItem ) )
2378 SfxViewFrame* pFrm = ((const SfxViewFrameItem*)pRetItem)->GetFrame();
2379 if (pFrm)
2380 pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() );
2382 if (pDestShell)
2383 pDestViewSh = pDestShell->GetBestViewShell();
2386 else
2387 pDestShell = ScDocShell::GetShellByNum( nDestDocNo );
2389 if (!pDestShell)
2391 OSL_FAIL("Dest-Doc nicht gefunden !!!");
2392 return;
2395 ScMarkData& rMark = GetViewData()->GetMarkData();
2396 if (bRename && rMark.GetSelectCount() != 1)
2398 // Custom sheet name is provided, but more than one sheet is selected.
2399 // We don't support this scenario at the moment.
2400 return;
2403 pDestDoc = pDestShell->GetDocument();
2405 SCTAB nTab = GetViewData()->GetTabNo();
2407 if (pDestDoc != pDoc)
2409 if (bNewDoc)
2411 while (pDestDoc->GetTableCount() > 1)
2412 pDestDoc->DeleteTab(0);
2413 pDestDoc->RenameTab( 0, OUString("______42_____"),
2414 false );
2417 SCTAB nTabCount = pDoc->GetTableCount();
2418 SCTAB nTabSelCount = rMark.GetSelectCount();
2420 vector<SCTAB> TheTabs;
2422 for(SCTAB i=0; i<nTabCount; ++i)
2424 if(rMark.GetTableSelect(i))
2426 OUString aTabName;
2427 pDoc->GetName( i, aTabName);
2428 TheTabs.push_back(i);
2429 for(SCTAB j=i+1;j<nTabCount;j++)
2431 if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2433 pDoc->GetName( j, aTabName);
2434 TheTabs.push_back(j);
2435 i=j;
2437 else break;
2442 GetFrameWin()->EnterWait();
2444 if (pDoc->GetDrawLayer())
2445 pDestShell->MakeDrawLayer();
2447 if (!bNewDoc && bUndo)
2448 pDestDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2450 sal_uLong nErrVal =1;
2451 if(nDestTab==SC_TAB_APPEND)
2452 nDestTab=pDestDoc->GetTableCount();
2453 SCTAB nDestTab1=nDestTab;
2454 ScClipParam aParam;
2455 for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 )
2456 { // insert sheets first and update all references
2457 OUString aName;
2458 if (bRename)
2459 aName = *pNewTabName;
2460 else
2461 pDoc->GetName( TheTabs[j], aName );
2463 pDestDoc->CreateValidTabName( aName );
2464 if ( !pDestDoc->InsertTab( nDestTab1, aName ) )
2466 nErrVal = 0; // total error
2467 break; // for
2469 ScRange aRange( 0, 0, TheTabs[j], MAXCOL, MAXROW, TheTabs[j] );
2470 aParam.maRanges.Append(aRange);
2472 pDoc->SetClipParam(aParam);
2473 if ( nErrVal > 0 )
2475 nDestTab1 = nDestTab;
2476 for(sal_uInt16 i=0; i<TheTabs.size();++i)
2478 nErrVal = pDestShell->TransferTab( *pDocShell, TheTabs[i], static_cast<SCTAB>(nDestTab1), false, false );
2479 nDestTab1++;
2482 OUString sName;
2483 if (!bNewDoc && bUndo)
2485 pDestDoc->GetName(nDestTab, sName);
2486 pDestShell->GetUndoManager()->AddUndoAction(
2487 new ScUndoImportTab( pDestShell, nDestTab,
2488 static_cast<SCTAB>(TheTabs.size())));
2491 else
2493 pDestShell->GetUndoManager()->Clear();
2496 GetFrameWin()->LeaveWait();
2497 switch (nErrVal)
2499 case 0: // internal error or full of errors
2501 ErrorMessage(STR_TABINSERT_ERROR);
2502 return;
2504 //break;
2505 case 2:
2506 ErrorMessage(STR_ABSREFLOST);
2507 break;
2508 case 3:
2509 ErrorMessage(STR_NAMECONFLICT);
2510 break;
2511 case 4:
2513 ErrorMessage(STR_ABSREFLOST);
2514 ErrorMessage(STR_NAMECONFLICT);
2516 break;
2517 default:
2518 break;
2521 if (!bCopy)
2523 if(nTabCount!=nTabSelCount)
2524 DeleteTables(TheTabs); // incl. Paint & Undo
2525 else
2526 ErrorMessage(STR_TABREMOVE_ERROR);
2529 if (bNewDoc)
2531 // ChartListenerCollection must be updated before DeleteTab
2532 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
2533 pDestDoc->UpdateChartListenerCollection();
2535 pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size())); // old first table
2536 if (pDestViewSh)
2538 // Make sure to clear the cached page view after sheet
2539 // deletion, which still points to the sdr page belonging to
2540 // the deleted sheet.
2541 SdrView* pSdrView = pDestViewSh->GetSdrView();
2542 if (pSdrView)
2543 pSdrView->ClearPageView();
2545 pDestViewSh->TabChanged(); // Pages auf dem Drawing-Layer
2547 pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2548 PAINT_GRID | PAINT_TOP | PAINT_LEFT |
2549 PAINT_EXTRAS | PAINT_SIZE );
2550 // PAINT_SIZE for outline
2552 else
2554 pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) );
2555 pDestShell->PostPaintExtras();
2556 pDestShell->PostPaintGridAll();
2559 TheTabs.clear();
2561 pDestShell->SetDocumentModified();
2562 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2564 else
2566 // Move or copy within the same document.
2567 SCTAB nTabCount = pDoc->GetTableCount();
2569 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2570 auto_ptr< vector<SCTAB> > pSrcTabs(new vector<SCTAB>);
2571 auto_ptr< vector<SCTAB> > pDestTabs(new vector<SCTAB>);
2572 auto_ptr< vector<OUString> > pTabNames(new vector<OUString>);
2573 auto_ptr< vector<OUString> > pDestNames(NULL);
2574 SAL_WNODEPRECATED_DECLARATIONS_POP
2575 pSrcTabs->reserve(nTabCount);
2576 pDestTabs->reserve(nTabCount);
2577 pTabNames->reserve(nTabCount);
2578 OUString aDestName;
2580 for(SCTAB i=0;i<nTabCount;i++)
2582 if(rMark.GetTableSelect(i))
2584 OUString aTabName;
2585 pDoc->GetName( i, aTabName);
2586 pTabNames->push_back(aTabName);
2588 for(SCTAB j=i+1;j<nTabCount;j++)
2590 if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2592 pDoc->GetName( j, aTabName);
2593 pTabNames->push_back(aTabName);
2594 i=j;
2596 else break;
2601 if (bCopy && bUndo)
2602 pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2604 pDoc->GetName( nDestTab, aDestName);
2605 SCTAB nDestTab1=nDestTab;
2606 SCTAB nMovTab=0;
2607 for (size_t j = 0, n = pTabNames->size(); j < n; ++j)
2609 nTabCount = pDoc->GetTableCount();
2610 const OUString& rStr = (*pTabNames)[j];
2611 if(!pDoc->GetTable(rStr,nMovTab))
2613 nMovTab=nTabCount;
2615 if(!pDoc->GetTable(aDestName,nDestTab1))
2617 nDestTab1=nTabCount;
2619 pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, false ); // Undo is here
2621 if(bCopy && pDoc->IsScenario(nMovTab))
2623 OUString aComment;
2624 Color aColor;
2625 sal_uInt16 nFlags;
2627 pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags);
2628 pDoc->SetScenario(nDestTab1,true);
2629 pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags);
2630 bool bActive = pDoc->IsActiveScenario(nMovTab );
2631 pDoc->SetActiveScenario( nDestTab1, bActive );
2632 bool bVisible=pDoc->IsVisible(nMovTab);
2633 pDoc->SetVisible(nDestTab1,bVisible );
2636 pSrcTabs->push_back(nMovTab);
2638 if(!bCopy)
2640 if(!pDoc->GetTable(rStr,nDestTab1))
2642 nDestTab1=nTabCount;
2646 pDestTabs->push_back(nDestTab1);
2649 // Rename must be done after all sheets have been moved.
2650 if (bRename)
2652 pDestNames.reset(new vector<OUString>);
2653 size_t n = pDestTabs->size();
2654 pDestNames->reserve(n);
2655 for (size_t j = 0; j < n; ++j)
2657 SCTAB nRenameTab = (*pDestTabs)[j];
2658 OUString aTabName = *pNewTabName;
2659 pDoc->CreateValidTabName( aTabName );
2660 pDestNames->push_back(aTabName);
2661 pDoc->RenameTab(nRenameTab, aTabName);
2664 else
2665 // No need to keep this around when we are not renaming.
2666 pTabNames.reset();
2668 nTab = GetViewData()->GetTabNo();
2670 if (bUndo)
2672 if (bCopy)
2674 pDocShell->GetUndoManager()->AddUndoAction(
2675 new ScUndoCopyTab(
2676 pDocShell, pSrcTabs.release(), pDestTabs.release(), pDestNames.release()));
2678 else
2680 pDocShell->GetUndoManager()->AddUndoAction(
2681 new ScUndoMoveTab(
2682 pDocShell, pSrcTabs.release(), pDestTabs.release(), pTabNames.release(), pDestNames.release()));
2686 SCTAB nNewTab = nDestTab;
2687 if (nNewTab == SC_TAB_APPEND)
2688 nNewTab = pDoc->GetTableCount()-1;
2689 else if (!bCopy && nTab<nDestTab)
2690 nNewTab--;
2692 SetTabNo( nNewTab, true );
2694 //#i29848# adjust references to data on the copied sheet
2695 if( bCopy )
2696 ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab );
2701 void ScViewFunc::ShowTable( const std::vector<OUString>& rNames )
2703 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2704 ScDocument* pDoc = pDocSh->GetDocument();
2705 bool bUndo(pDoc->IsUndoEnabled());
2707 std::vector<SCTAB> undoTabs;
2708 OUString aName;
2709 SCTAB nPos = 0;
2711 bool bFound(false);
2713 for (std::vector<OUString>::const_iterator itr=rNames.begin(), itrEnd = rNames.end(); itr!=itrEnd; ++itr)
2715 aName = *itr;
2716 if (pDoc->GetTable(aName, nPos))
2718 pDoc->SetVisible( nPos, true );
2719 SetTabNo( nPos, true );
2720 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2721 if (!bFound)
2722 bFound = true;
2723 if (bUndo)
2724 undoTabs.push_back(nPos);
2727 if (bFound)
2729 if (bUndo)
2731 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, undoTabs, true ) );
2733 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2734 pDocSh->SetDocumentModified();
2739 void ScViewFunc::HideTable( const ScMarkData& rMark )
2741 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2742 ScDocument* pDoc = pDocSh->GetDocument();
2743 bool bUndo(pDoc->IsUndoEnabled());
2744 SCTAB nVisible = 0;
2745 SCTAB nTabCount = pDoc->GetTableCount();
2747 SCTAB nTabSelCount = rMark.GetSelectCount();
2749 // check to make sure we won't hide all sheets. we need at least one visible at all times.
2750 for ( SCTAB i=0; i < nTabCount && nVisible <= nTabSelCount ; i++ )
2751 if (pDoc->IsVisible(i))
2752 ++nVisible;
2754 if (nVisible > nTabSelCount)
2756 SCTAB nTab;
2757 ScMarkData::MarkedTabsType::const_iterator it;
2758 std::vector<SCTAB> undoTabs;
2760 ScMarkData::MarkedTabsType selectedTabs = rMark.GetSelectedTabs();
2761 for (it=selectedTabs.begin(); it!=selectedTabs.end(); ++it)
2763 nTab = *it;
2764 if (pDoc->IsVisible( nTab ))
2766 pDoc->SetVisible( nTab, false );
2767 // Update views
2768 pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2769 SetTabNo( nTab, true );
2770 // Store for undo
2771 if (bUndo)
2772 undoTabs.push_back(nTab);
2775 if (bUndo)
2777 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, undoTabs, false ) );
2780 // Update views
2781 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2782 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2783 pDocSh->SetDocumentModified();
2788 void ScViewFunc::InsertSpecialChar( const OUString& rStr, const Font& rFont )
2790 ScEditableTester aTester( this );
2791 if (!aTester.IsEditable())
2793 ErrorMessage(aTester.GetMessageId());
2794 return;
2797 const sal_Unicode* pChar = rStr.getStr();
2798 ScTabViewShell* pViewShell = GetViewData()->GetViewShell();
2799 SvxFontItem aFontItem( rFont.GetFamily(),
2800 rFont.GetName(),
2801 rFont.GetStyleName(),
2802 rFont.GetPitch(),
2803 rFont.GetCharSet(),
2804 ATTR_FONT );
2806 // if string contains WEAK characters, set all fonts
2807 sal_uInt8 nScript;
2808 ScDocument* pDoc = GetViewData()->GetDocument();
2809 if ( pDoc->HasStringWeakCharacters( rStr ) )
2810 nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX;
2811 else
2812 nScript = pDoc->GetStringScriptType( rStr );
2814 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() );
2815 aSetItem.PutItemForScriptType( nScript, aFontItem );
2816 ApplyUserItemSet( aSetItem.GetItemSet() );
2818 while ( *pChar )
2819 pViewShell->TabKeyInput( KeyEvent( *(pChar++), KeyCode() ) );
2823 void ScViewFunc::UpdateLineAttrs( SvxBorderLine& rLine,
2824 const SvxBorderLine* pDestLine,
2825 const SvxBorderLine* pSrcLine,
2826 bool bColor )
2828 if ( pSrcLine && pDestLine )
2830 if ( bColor )
2832 rLine.SetColor ( pSrcLine->GetColor() );
2833 rLine.SetBorderLineStyle(pDestLine->GetBorderLineStyle());
2834 rLine.SetWidth ( pDestLine->GetWidth() );
2836 else
2838 rLine.SetColor ( pDestLine->GetColor() );
2839 rLine.SetBorderLineStyle(pSrcLine->GetBorderLineStyle());
2840 rLine.SetWidth ( pSrcLine->GetWidth() );
2846 #define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \
2847 pBoxLine = aBoxItem.Get##LINE(); \
2848 if ( pBoxLine ) \
2850 if ( pLine ) \
2852 UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \
2853 aBoxItem.SetLine( &aLine, BOXLINE ); \
2855 else \
2856 aBoxItem.SetLine( NULL, BOXLINE ); \
2860 void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine,
2861 bool bColorOnly )
2863 // Not editable only due to a matrix? Attribute is ok anyhow.
2864 bool bOnlyNotBecauseOfMatrix;
2865 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2867 ErrorMessage(STR_PROTECTIONERR);
2868 return;
2871 ScDocument* pDoc = GetViewData()->GetDocument();
2872 ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered
2873 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
2874 ScDocShell* pDocSh = GetViewData()->GetDocShell();
2875 const ScPatternAttr* pSelAttrs = GetSelectionPattern();
2876 const SfxItemSet& rSelItemSet = pSelAttrs->GetItemSet();
2878 const SfxPoolItem* pBorderAttr = NULL;
2879 SfxItemState eItemState = rSelItemSet.GetItemState( ATTR_BORDER, true, &pBorderAttr );
2881 const SfxPoolItem* pTLBRItem = 0;
2882 SfxItemState eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, true, &pTLBRItem );
2884 const SfxPoolItem* pBLTRItem = 0;
2885 SfxItemState eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, true, &pBLTRItem );
2887 // any of the lines visible?
2888 if( (eItemState != SFX_ITEM_DEFAULT) || (eTLBRState != SFX_ITEM_DEFAULT) || (eBLTRState != SFX_ITEM_DEFAULT) )
2890 // none of the lines don't care?
2891 if( (eItemState != SFX_ITEM_DONTCARE) && (eTLBRState != SFX_ITEM_DONTCARE) && (eBLTRState != SFX_ITEM_DONTCARE) )
2893 boost::scoped_ptr<SfxItemSet> pOldSet(new SfxItemSet(
2894 *(pDoc->GetPool()),
2895 ATTR_PATTERN_START,
2896 ATTR_PATTERN_END ));
2897 boost::scoped_ptr<SfxItemSet> pNewSet(new SfxItemSet(
2898 *(pDoc->GetPool()),
2899 ATTR_PATTERN_START,
2900 ATTR_PATTERN_END ));
2903 const SvxBorderLine* pBoxLine = NULL;
2904 SvxBorderLine aLine;
2906 // here pBoxLine is used
2908 if( pBorderAttr )
2910 SvxBoxItem aBoxItem( *(const SvxBoxItem*)pBorderAttr );
2911 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
2913 SET_LINE_ATTRIBUTES(Top,BOX_LINE_TOP)
2914 SET_LINE_ATTRIBUTES(Bottom,BOX_LINE_BOTTOM)
2915 SET_LINE_ATTRIBUTES(Left,BOX_LINE_LEFT)
2916 SET_LINE_ATTRIBUTES(Right,BOX_LINE_RIGHT)
2918 aBoxInfoItem.SetLine( aBoxItem.GetTop(), BOXINFO_LINE_HORI );
2919 aBoxInfoItem.SetLine( aBoxItem.GetLeft(), BOXINFO_LINE_VERT );
2920 aBoxInfoItem.ResetFlags(); // set Lines to Valid
2922 pOldSet->Put( *pBorderAttr );
2923 pNewSet->Put( aBoxItem );
2924 pNewSet->Put( aBoxInfoItem );
2927 if( pTLBRItem && ((const SvxLineItem*)pTLBRItem)->GetLine() )
2929 SvxLineItem aTLBRItem( *(const SvxLineItem*)pTLBRItem );
2930 UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly );
2931 aTLBRItem.SetLine( &aLine );
2932 pOldSet->Put( *pTLBRItem );
2933 pNewSet->Put( aTLBRItem );
2936 if( pBLTRItem && ((const SvxLineItem*)pBLTRItem)->GetLine() )
2938 SvxLineItem aBLTRItem( *(const SvxLineItem*)pBLTRItem );
2939 UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly );
2940 aBLTRItem.SetLine( &aLine );
2941 pOldSet->Put( *pBLTRItem );
2942 pNewSet->Put( aBLTRItem );
2945 ApplyAttributes( pNewSet.get(), pOldSet.get() );
2947 else // if ( eItemState == SFX_ITEM_DONTCARE )
2949 aFuncMark.MarkToMulti();
2950 pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly );
2953 ScRange aMarkRange;
2954 aFuncMark.GetMultiMarkArea( aMarkRange );
2955 SCCOL nStartCol = aMarkRange.aStart.Col();
2956 SCROW nStartRow = aMarkRange.aStart.Row();
2957 SCTAB nStartTab = aMarkRange.aStart.Tab();
2958 SCCOL nEndCol = aMarkRange.aEnd.Col();
2959 SCROW nEndRow = aMarkRange.aEnd.Row();
2960 SCTAB nEndTab = aMarkRange.aEnd.Tab();
2961 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
2962 nEndCol, nEndRow, nEndTab,
2963 PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
2965 pDocSh->UpdateOle( GetViewData() );
2966 pDocSh->SetDocumentModified();
2970 #undef SET_LINE_ATTRIBUTES
2972 void ScViewFunc::SetValidation( const ScValidationData& rNew )
2974 ScDocument* pDoc = GetViewData()->GetDocument();
2975 sal_uLong nIndex = pDoc->AddValidationEntry(rNew); // for it there is no Undo
2976 SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex );
2978 ApplyAttr( aItem ); // with Paint and Undo...
2982 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */