fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / view / viewfun2.cxx
blob47b0ace1ccef6f8538845675345b5824d4bc9990
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 "docoptio.hxx"
60 #include "global.hxx"
61 #include "patattr.hxx"
62 #include "printfun.hxx"
63 #include "rangenam.hxx"
64 #include "rangeutl.hxx"
65 #include "refundo.hxx"
66 #include "table.hxx"
67 #include "tablink.hxx"
68 #include "tabvwsh.hxx"
69 #include "uiitems.hxx"
70 #include "undoblk.hxx"
71 #include "undocell.hxx"
72 #include "undotab.hxx"
73 #include "sizedev.hxx"
74 #include "editable.hxx"
75 #include "scmod.hxx"
76 #include "inputhdl.hxx"
77 #include "inputwin.hxx"
78 #include "funcdesc.hxx"
79 #include "docuno.hxx"
80 #include "charthelper.hxx"
81 #include "tabbgcolor.hxx"
82 #include "clipparam.hxx"
83 #include "prnsave.hxx"
84 #include "searchresults.hxx"
85 #include "tokenarray.hxx"
86 #include <columnspanset.hxx>
87 #include <rowheightcontext.hxx>
88 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
90 #include <boost/scoped_ptr.hpp>
91 #include <vector>
92 #include <memory>
94 using namespace com::sun::star;
95 using ::editeng::SvxBorderLine;
97 using ::std::vector;
98 using ::std::unique_ptr;
100 // STATIC DATA ---------------------------------------------------------------
102 bool ScViewFunc::AdjustBlockHeight( bool bPaint, ScMarkData* pMarkData )
104 ScDocShell* pDocSh = GetViewData().GetDocShell();
105 if (!pMarkData)
106 pMarkData = &GetViewData().GetMarkData();
108 ScDocument& rDoc = pDocSh->GetDocument();
109 std::vector<sc::ColRowSpan> aMarkedRows = pMarkData->GetMarkedRowSpans();
111 if (aMarkedRows.empty())
113 SCROW nCurRow = GetViewData().GetCurY();
114 aMarkedRows.push_back(sc::ColRowSpan(nCurRow, nCurRow));
117 double nPPTX = GetViewData().GetPPTX();
118 double nPPTY = GetViewData().GetPPTY();
119 Fraction aZoomX = GetViewData().GetZoomX();
120 Fraction aZoomY = GetViewData().GetZoomY();
122 ScSizeDeviceProvider aProv(pDocSh);
123 if (aProv.IsPrinter())
125 nPPTX = aProv.GetPPTX();
126 nPPTY = aProv.GetPPTY();
127 aZoomX = aZoomY = Fraction( 1, 1 );
130 sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
131 bool bAnyChanged = false;
132 ScMarkData::iterator itr = pMarkData->begin(), itrEnd = pMarkData->end();
133 for (; itr != itrEnd; ++itr)
135 SCTAB nTab = *itr;
136 bool bChanged = false;
137 SCROW nPaintY = 0;
138 std::vector<sc::ColRowSpan>::const_iterator itRows = aMarkedRows.begin(), itRowsEnd = aMarkedRows.end();
139 for (; itRows != itRowsEnd; ++itRows)
141 SCROW nStartNo = itRows->mnStart;
142 SCROW nEndNo = itRows->mnEnd;
143 ScAddress aTopLeft(0, nStartNo, nTab);
144 rDoc.UpdateScriptTypes(aTopLeft, MAXCOLCOUNT, nEndNo-nStartNo+1);
145 if (rDoc.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;
163 bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, bool bPaint )
165 ScDocShell* pDocSh = GetViewData().GetDocShell();
166 ScDocument& rDoc = pDocSh->GetDocument();
167 SCTAB nTab = GetViewData().GetTabNo();
168 double nPPTX = GetViewData().GetPPTX();
169 double nPPTY = GetViewData().GetPPTY();
170 Fraction aZoomX = GetViewData().GetZoomX();
171 Fraction aZoomY = GetViewData().GetZoomY();
172 sal_uInt16 nOldPixel = 0;
173 if (nStartRow == nEndRow)
174 nOldPixel = (sal_uInt16) (rDoc.GetRowHeight(nStartRow,nTab) * nPPTY);
176 ScSizeDeviceProvider aProv(pDocSh);
177 if (aProv.IsPrinter())
179 nPPTX = aProv.GetPPTX();
180 nPPTY = aProv.GetPPTY();
181 aZoomX = aZoomY = Fraction( 1, 1 );
183 sc::RowHeightContext aCxt(nPPTX, nPPTY, aZoomX, aZoomY, aProv.GetDevice());
184 bool bChanged = rDoc.SetOptimalHeight(aCxt, nStartRow, nEndRow, nTab);
186 if (bChanged && ( nStartRow == nEndRow ))
188 sal_uInt16 nNewPixel = (sal_uInt16) (rDoc.GetRowHeight(nStartRow,nTab) * nPPTY);
189 if ( nNewPixel == nOldPixel )
190 bChanged = false;
193 if ( bPaint && bChanged )
194 pDocSh->PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
195 PAINT_GRID | PAINT_LEFT );
197 return bChanged;
200 enum ScAutoSum
202 ScAutoSumNone = 0,
203 ScAutoSumData,
204 ScAutoSumSum
207 static ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow,
208 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
210 ScRefCellValue aCell;
211 aCell.assign(*pDoc, ScAddress(nCol, nRow, nTab));
212 if (aCell.hasNumeric())
214 if (aCell.meType == CELLTYPE_FORMULA)
216 ScTokenArray* pCode = aCell.mpFormula->GetCode();
217 if ( pCode && pCode->GetOuterFuncOpCode() == ocSum )
219 if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend,
220 ScAddress( nCol, nRow, nTab ), eDir ) )
221 return ScAutoSumSum;
224 return ScAutoSumData;
226 return ScAutoSumNone;
229 #define SC_AUTOSUM_MAXCOUNT 20
231 static ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow,
232 SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
234 sal_uInt16 nCount = 0;
235 while (nCount < SC_AUTOSUM_MAXCOUNT)
237 if ( eDir == DIR_TOP )
239 if (nRow > 0)
240 --nRow;
241 else
242 return ScAutoSumNone;
244 else
246 if (nCol > 0)
247 --nCol;
248 else
249 return ScAutoSumNone;
251 ScAutoSum eSum;
252 if ( (eSum = lcl_IsAutoSumData(
253 pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone )
254 return eSum;
255 ++nCount;
257 return ScAutoSumNone;
260 #undef SC_AUTOSUM_MAXCOUNT
262 static bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow,
263 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow )
265 const SCROW nTmp = nRow;
266 ScAutoSum eSkip = ScAutoSumNone;
267 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData &&
268 nRow > nMinRow )
270 --nRow;
272 if ( eSkip == ScAutoSumSum && nRow < nTmp )
274 return true;
276 return false;
279 static bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow,
280 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol )
282 const SCCOL nTmp = nCol;
283 ScAutoSum eSkip = ScAutoSumNone;
284 while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData &&
285 nCol > nMinCol )
287 --nCol;
289 if ( eSkip == ScAutoSumSum && nCol < nTmp )
291 return true;
293 return false;
296 static bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
298 const ScAddress aStart = rRange.aStart;
299 const ScAddress aEnd = rRange.aEnd;
300 if ( aStart.Col() != aEnd.Col() )
302 return false;
305 const SCTAB nTab = aEnd.Tab();
306 const SCCOL nCol = aEnd.Col();
307 SCROW nEndRow = aEnd.Row();
308 SCROW nStartRow = nEndRow;
309 SCCOLROW nExtend = 0;
310 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ );
312 if ( eSum == ScAutoSumSum )
314 bool bContinue = false;
317 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
318 nEndRow = static_cast< SCROW >( nExtend );
319 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) )
321 nStartRow = nEndRow;
323 } while ( bContinue );
325 else
327 while ( nStartRow > aStart.Row() &&
328 lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum )
330 --nStartRow;
332 rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
335 return true;
338 static bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
340 const ScAddress aStart = rRange.aStart;
341 const ScAddress aEnd = rRange.aEnd;
342 if ( aStart.Row() != aEnd.Row() )
344 return false;
347 const SCTAB nTab = aEnd.Tab();
348 const SCROW nRow = aEnd.Row();
349 SCCOL nEndCol = aEnd.Col();
350 SCCOL nStartCol = nEndCol;
351 SCCOLROW nExtend = 0;
352 const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ );
354 if ( eSum == ScAutoSumSum )
356 bool bContinue = false;
359 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
360 nEndCol = static_cast< SCCOL >( nExtend );
361 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) )
363 nStartCol = nEndCol;
365 } while ( bContinue );
367 else
369 while ( nStartCol > aStart.Col() &&
370 lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum )
372 --nStartCol;
374 rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
377 return true;
380 bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList )
382 ScDocument* pDoc = GetViewData().GetDocument();
383 SCTAB nTab = GetViewData().GetTabNo();
385 SCCOL nCol = GetViewData().GetCurX();
386 SCROW nRow = GetViewData().GetCurY();
388 SCCOL nStartCol = nCol;
389 SCROW nStartRow = nRow;
390 SCCOL nEndCol = nCol;
391 SCROW nEndRow = nRow;
392 SCCOL nSeekCol = nCol;
393 SCROW nSeekRow = nRow;
394 SCCOLROW nExtend; // will become valid via reference for ScAutoSumSum
396 bool bCol = false;
397 bool bRow = false;
399 ScAutoSum eSum;
400 if ( nRow != 0
401 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
402 DIR_TOP, nExtend /*out*/ )) == ScAutoSumData )
403 && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
404 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
407 bRow = true;
408 nSeekRow = nRow - 1;
410 else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab,
411 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
413 bCol = true;
414 nSeekCol = nCol - 1;
416 else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone )
417 bRow = true;
418 else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone )
419 bCol = true;
421 if ( bCol || bRow )
423 if ( bRow )
425 nStartRow = nSeekRow; // nSeekRow might be adjusted via reference
426 if ( eSum == ScAutoSumSum )
427 nEndRow = nStartRow; // only sum sums
428 else
429 nEndRow = nRow - 1; // maybe extend data area at bottom
431 else
433 nStartCol = nSeekCol; // nSeekCol might be adjusted vie reference
434 if ( eSum == ScAutoSumSum )
435 nEndCol = nStartCol; // only sum sums
436 else
437 nEndCol = nCol - 1; // maybe extend data area to the right
439 bool bContinue = false;
442 if ( eSum == ScAutoSumData )
444 if ( bRow )
446 while ( nStartRow != 0 && lcl_IsAutoSumData( pDoc, nCol,
447 nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum )
448 --nStartRow;
450 else
452 while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1,
453 nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum )
454 --nStartCol;
457 rRangeList.Append(
458 ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) );
459 if ( eSum == ScAutoSumSum )
461 if ( bRow )
463 nEndRow = static_cast< SCROW >( nExtend );
464 if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) )
466 nStartRow = nEndRow;
469 else
471 nEndCol = static_cast< SCCOL >( nExtend );
472 if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) )
474 nStartCol = nEndCol;
478 } while ( bContinue );
479 return true;
481 return false;
484 void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr)
486 OUString aFormula = GetAutoSumFormula( rRangeList, bSubTotal, rAddr );
487 EnterBlock( aFormula, NULL );
490 bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue )
492 ScDocument* pDoc = GetViewData().GetDocument();
493 const SCTAB nTab = rRange.aStart.Tab();
494 SCCOL nStartCol = rRange.aStart.Col();
495 SCROW nStartRow = rRange.aStart.Row();
496 const SCCOL nEndCol = rRange.aEnd.Col();
497 const SCROW nEndRow = rRange.aEnd.Row();
498 SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData
500 // ignore rows at the top of the given range which don't contain autosum data
501 bool bRowData = false;
502 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
504 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
506 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone )
508 bRowData = true;
509 break;
512 if ( bRowData )
514 nStartRow = nRow;
515 break;
518 if ( !bRowData )
520 return false;
523 // ignore columns at the left of the given range which don't contain autosum data
524 bool bColData = false;
525 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
527 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
529 if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone )
531 bColData = true;
532 break;
535 if ( bColData )
537 nStartCol = nCol;
538 break;
541 if ( !bColData )
543 return false;
546 const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow );
547 const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow );
548 bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) );
549 bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) );
551 // find an empty row for entering the result
552 SCROW nInsRow = nEndRow;
553 if ( bRow && !bEndRowEmpty )
555 if ( nInsRow < MAXROW )
557 ++nInsRow;
558 while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) )
560 if ( nInsRow < MAXROW )
562 ++nInsRow;
564 else
566 bRow = false;
567 break;
571 else
573 bRow = false;
577 // find an empty column for entering the result
578 SCCOL nInsCol = nEndCol;
579 if ( bCol && !bEndColEmpty )
581 if ( nInsCol < MAXCOL )
583 ++nInsCol;
584 while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) )
586 if ( nInsCol < MAXCOL )
588 ++nInsCol;
590 else
592 bCol = false;
593 break;
597 else
599 bCol = false;
603 if ( !bRow && !bCol )
605 return false;
608 SCCOL nMarkEndCol = nEndCol;
609 SCROW nMarkEndRow = nEndRow;
611 if ( bRow )
613 // calculate the row sums for all columns of the given range
615 SCROW nSumEndRow = nEndRow;
617 if ( bEndRowEmpty )
619 // the last row of the given range is empty;
620 // don't take into account for calculating the autosum
621 --nSumEndRow;
623 else
625 // increase mark range
626 ++nMarkEndRow;
629 for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
631 if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) )
633 ScRangeList aRangeList;
634 const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab );
635 if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) )
637 const OUString aFormula = GetAutoSumFormula(
638 aRangeList, bSubTotal, ScAddress(nCol, nInsRow, nTab));
639 EnterData( nCol, nInsRow, nTab, aFormula );
645 if ( bCol )
647 // calculate the column sums for all rows of the given range
649 SCCOL nSumEndCol = nEndCol;
651 if ( bEndColEmpty )
653 // the last column of the given range is empty;
654 // don't take into account for calculating the autosum
655 --nSumEndCol;
657 else
659 // increase mark range
660 ++nMarkEndCol;
663 for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
665 if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) )
667 ScRangeList aRangeList;
668 const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab );
669 if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) )
671 const OUString aFormula = GetAutoSumFormula( aRangeList, bSubTotal, ScAddress(nInsCol, nRow, nTab) );
672 EnterData( nInsCol, nRow, nTab, aFormula );
678 // set new mark range and cursor position
679 const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab );
680 MarkRange( aMarkRange, false, bContinue );
681 if ( bSetCursor )
683 SetCursor( nMarkEndCol, nMarkEndRow );
686 return true;
689 OUString ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal, const ScAddress& rAddr )
691 ScViewData& rViewData = GetViewData();
692 ScDocument* pDoc = rViewData.GetDocument();
693 ::boost::scoped_ptr<ScTokenArray> pArray(new ScTokenArray);
695 pArray->AddOpCode(bSubTotal ? ocSubTotal : ocSum);
696 pArray->AddOpCode(ocOpen);
698 if (bSubTotal)
700 pArray->AddDouble(9);
701 pArray->AddOpCode(ocSep);
704 if(!rRangeList.empty())
706 ScRangeList aRangeList = rRangeList;
707 const ScRange* pFirst = aRangeList.front();
708 size_t ListSize = aRangeList.size();
709 for ( size_t i = 0; i < ListSize; ++i )
711 const ScRange* p = aRangeList[i];
712 if (p != pFirst)
713 pArray->AddOpCode(ocSep);
714 ScComplexRefData aRef;
715 aRef.InitRangeRel(*p, rAddr);
716 pArray->AddDoubleReference(aRef);
720 pArray->AddOpCode(ocClose);
722 ScCompiler aComp(pDoc, rAddr, *pArray);
723 aComp.SetGrammar(pDoc->GetGrammar());
724 OUStringBuffer aBuf;
725 aComp.CreateStringFromTokenArray(aBuf);
726 OUString aFormula = aBuf.makeStringAndClear();
727 aBuf.append('=');
728 aBuf.append(aFormula);
729 return aBuf.makeStringAndClear();
732 void ScViewFunc::EnterBlock( const OUString& rString, const EditTextObject* pData )
734 // test for multi selection
736 SCCOL nCol = GetViewData().GetCurX();
737 SCROW nRow = GetViewData().GetCurY();
738 SCTAB nTab = GetViewData().GetTabNo();
739 ScMarkData& rMark = GetViewData().GetMarkData();
740 if ( rMark.IsMultiMarked() )
742 rMark.MarkToSimple();
743 if ( rMark.IsMultiMarked() )
744 { // "Insert into multi selection not possible"
745 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
747 // insert into single cell
748 if ( pData )
749 EnterData(nCol, nRow, nTab, *pData);
750 else
751 EnterData( nCol, nRow, nTab, rString );
752 return;
756 ScDocument* pDoc = GetViewData().GetDocument();
757 OUString aNewStr = rString;
758 if ( pData )
760 const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
761 ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
762 aEngine.SetText(*pData);
764 ScEditAttrTester aTester( &aEngine );
765 if (!aTester.NeedsObject())
767 aNewStr = aEngine.GetText();
768 pData = NULL;
772 // Insert via PasteFromClip
774 WaitObject aWait( GetFrameWin() );
776 ScAddress aPos( nCol, nRow, nTab );
778 boost::scoped_ptr<ScDocument> pInsDoc(new ScDocument( SCDOCMODE_CLIP ));
779 pInsDoc->ResetClip( pDoc, nTab );
781 if (aNewStr[0] == '=') // Formula ?
783 // SetString not possible, because in Clipboard-Documents nothing will be compiled!
784 pInsDoc->SetFormulaCell(aPos, new ScFormulaCell(pDoc, aPos, aNewStr));
786 else if ( pData )
788 // A copy of pData will be stored.
789 pInsDoc->SetEditText(aPos, *pData, pDoc->GetEditPool());
791 else
792 pInsDoc->SetString( nCol, nRow, nTab, aNewStr );
794 pInsDoc->SetClipArea( ScRange(aPos) );
795 // insert Block, with Undo etc.
796 if ( PasteFromClip( IDF_CONTENTS, pInsDoc.get(), PASTE_NOFUNC, false, false,
797 false, INS_NONE, IDF_ATTRIB ) )
799 const SfxUInt32Item* pItem = static_cast<const SfxUInt32Item*>( pInsDoc->GetAttr(
800 nCol, nRow, nTab, ATTR_VALUE_FORMAT ) );
801 if ( pItem )
802 { // set number format if incompatible
803 // MarkData was already MarkToSimple'ed in PasteFromClip
804 ScRange aRange;
805 rMark.GetMarkArea( aRange );
806 boost::scoped_ptr<ScPatternAttr> pPattern(new ScPatternAttr( pDoc->GetPool() ));
807 pPattern->GetItemSet().Put( *pItem );
808 short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() );
809 pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark,
810 *pPattern, nNewType );
815 // manual page break
817 void ScViewFunc::InsertPageBreak( bool bColumn, bool bRecord, const ScAddress* pPos,
818 bool bSetModified )
820 SCTAB nTab = GetViewData().GetTabNo();
821 ScAddress aCursor;
822 if (pPos)
823 aCursor = *pPos;
824 else
825 aCursor = ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab );
827 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().
828 InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, false );
830 if ( bSuccess && bSetModified )
831 UpdatePageBreakData( true ); // for PageBreak-Mode
834 void ScViewFunc::DeletePageBreak( bool bColumn, bool bRecord, const ScAddress* pPos,
835 bool bSetModified )
837 SCTAB nTab = GetViewData().GetTabNo();
838 ScAddress aCursor;
839 if (pPos)
840 aCursor = *pPos;
841 else
842 aCursor = ScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab );
844 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().
845 RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, false );
847 if ( bSuccess && bSetModified )
848 UpdatePageBreakData( true ); // for PageBreak-Mode
851 void ScViewFunc::RemoveManualBreaks()
853 ScDocShell* pDocSh = GetViewData().GetDocShell();
854 ScDocument& rDoc = pDocSh->GetDocument();
855 SCTAB nTab = GetViewData().GetTabNo();
856 bool bUndo(rDoc.IsUndoEnabled());
858 if (bUndo)
860 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
861 pUndoDoc->InitUndo( &rDoc, nTab, nTab, true, true );
862 rDoc.CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, false, pUndoDoc );
863 pDocSh->GetUndoManager()->AddUndoAction(
864 new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) );
867 rDoc.RemoveManualBreaks(nTab);
868 rDoc.UpdatePageBreaks(nTab);
870 UpdatePageBreakData( true );
871 pDocSh->SetDocumentModified();
872 pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
875 void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages)
877 ScDocShell* pDocSh = GetViewData().GetDocShell();
878 SCTAB nTab = GetViewData().GetTabNo();
879 pDocSh->SetPrintZoom( nTab, nScale, nPages );
882 void ScViewFunc::AdjustPrintZoom()
884 ScRange aRange;
885 if ( GetViewData().GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
886 GetViewData().GetMarkData().GetMultiMarkArea( aRange );
887 GetViewData().GetDocShell()->AdjustPrintZoom( aRange );
890 void ScViewFunc::SetPrintRanges( bool bEntireSheet, const OUString* pPrint,
891 const OUString* pRepCol, const OUString* pRepRow,
892 bool bAddPrint )
894 // on all selected tables
896 ScDocShell* pDocSh = GetViewData().GetDocShell();
897 ScDocument& rDoc = pDocSh->GetDocument();
898 ScMarkData& rMark = GetViewData().GetMarkData();
899 SCTAB nTab;
900 bool bUndo (rDoc.IsUndoEnabled());
902 ScPrintRangeSaver* pOldRanges = rDoc.CreatePrintRangeSaver();
904 ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
906 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
907 for (; itr != itrEnd; ++itr)
909 nTab = *itr;
910 ScRange aRange( 0,0,nTab );
912 // print ranges
914 if( !bAddPrint )
915 rDoc.ClearPrintRanges( nTab );
917 if( bEntireSheet )
919 rDoc.SetPrintEntireSheet( nTab );
921 else if ( pPrint )
923 if ( !pPrint->isEmpty() )
925 const sal_Unicode sep = ScCompiler::GetNativeSymbolChar(ocSep);
926 sal_uInt16 nTCount = comphelper::string::getTokenCount(*pPrint, sep);
927 for (sal_uInt16 i=0; i<nTCount; i++)
929 OUString aToken = pPrint->getToken(i, sep);
930 if ( aRange.ParseAny( aToken, &rDoc, aDetails ) & SCA_VALID )
931 rDoc.AddPrintRange( nTab, aRange );
935 else // NULL = use selection (print range is always set), use empty string to delete all ranges
937 if ( GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
939 rDoc.AddPrintRange( nTab, aRange );
941 else if ( rMark.IsMultiMarked() )
943 rMark.MarkToMulti();
944 ScRangeListRef pList( new ScRangeList );
945 rMark.FillRangeListWithMarks( pList, false );
946 for (size_t i = 0, n = pList->size(); i < n; ++i)
948 ScRange* pR = (*pList)[i];
949 rDoc.AddPrintRange(nTab, *pR);
954 // repeat columns
956 if ( pRepCol )
958 if ( pRepCol->isEmpty() )
959 rDoc.SetRepeatColRange( nTab, NULL );
960 else
961 if ( aRange.ParseAny( *pRepCol, &rDoc, aDetails ) & SCA_VALID )
962 rDoc.SetRepeatColRange( nTab, &aRange );
965 // repeat rows
967 if ( pRepRow )
969 if ( pRepRow->isEmpty() )
970 rDoc.SetRepeatRowRange( nTab, NULL );
971 else
972 if ( aRange.ParseAny( *pRepRow, &rDoc, aDetails ) & SCA_VALID )
973 rDoc.SetRepeatRowRange( nTab, &aRange );
977 // undo (for all tables)
978 if (bUndo)
980 SCTAB nCurTab = GetViewData().GetTabNo();
981 ScPrintRangeSaver* pNewRanges = rDoc.CreatePrintRangeSaver();
982 pDocSh->GetUndoManager()->AddUndoAction(
983 new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) );
985 else
986 delete pOldRanges;
988 // update page breaks
990 itr = rMark.begin();
991 for (; itr != itrEnd; ++itr)
992 ScPrintFunc( pDocSh, pDocSh->GetPrinter(), *itr ).UpdatePages();
994 SfxBindings& rBindings = GetViewData().GetBindings();
995 rBindings.Invalidate( SID_DELETE_PRINTAREA );
997 pDocSh->SetDocumentModified();
1000 // Merge cells
1002 bool ScViewFunc::TestMergeCells() // pre-test (for menu)
1004 // simple test: true if there's a selection but no multi selection and not filtered
1006 const ScMarkData& rMark = GetViewData().GetMarkData();
1007 if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1009 ScRange aDummy;
1010 return GetViewData().GetSimpleArea( aDummy) == SC_MARK_SIMPLE;
1012 else
1013 return false;
1016 bool ScViewFunc::MergeCells( bool bApi, bool& rDoContents, bool bRecord, bool bCenter )
1018 // Editable- and Being-Nested- test must be at the beginning (in DocFunc too),
1019 // so that the Contents-QueryBox won't appear
1020 ScEditableTester aTester( this );
1021 if (!aTester.IsEditable())
1023 ErrorMessage(aTester.GetMessageId());
1024 return false;
1027 ScMarkData& rMark = GetViewData().GetMarkData();
1028 rMark.MarkToSimple();
1029 if (!rMark.IsMarked())
1031 ErrorMessage(STR_NOMULTISELECT);
1032 return false;
1035 ScDocShell* pDocSh = GetViewData().GetDocShell();
1036 ScDocument& rDoc = pDocSh->GetDocument();
1038 ScRange aMarkRange;
1039 rMark.GetMarkArea( aMarkRange );
1040 SCCOL nStartCol = aMarkRange.aStart.Col();
1041 SCROW nStartRow = aMarkRange.aStart.Row();
1042 SCTAB nStartTab = aMarkRange.aStart.Tab();
1043 SCCOL nEndCol = aMarkRange.aEnd.Col();
1044 SCROW nEndRow = aMarkRange.aEnd.Row();
1045 SCTAB nEndTab = aMarkRange.aEnd.Tab();
1046 if ( nStartCol == nEndCol && nStartRow == nEndRow )
1048 // nothing to do
1049 return true;
1052 if ( rDoc.HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1053 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1054 { // "Don't nest merging !"
1055 ErrorMessage(STR_MSSG_MERGECELLS_0);
1056 return false;
1059 // Check for the contents of all selected tables.
1060 bool bAskDialog = false;
1061 ScCellMergeOption aMergeOption(nStartCol, nStartRow, nEndCol, nEndRow, bCenter);
1062 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1063 for (; itr != itrEnd; ++itr)
1065 SCTAB i = *itr;
1066 aMergeOption.maTabs.insert(i);
1068 if (!rDoc.IsBlockEmpty(i, nStartCol, nStartRow+1, nStartCol, nEndRow) ||
1069 !rDoc.IsBlockEmpty(i, nStartCol+1, nStartRow, nEndCol, nEndRow))
1070 bAskDialog = true;
1073 bool bOk = true;
1075 if (bAskDialog)
1077 if (!bApi)
1079 ScopedVclPtrInstance<MessBox> aBox( GetViewData().GetDialogParent(),
1080 WinBits(WB_YES_NO_CANCEL | WB_DEF_NO),
1081 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
1082 ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) );
1083 sal_uInt16 nRetVal = aBox->Execute();
1085 if ( nRetVal == RET_YES )
1086 rDoContents = true;
1087 else if ( nRetVal == RET_CANCEL )
1088 bOk = false;
1092 if (bOk)
1094 bOk = pDocSh->GetDocFunc().MergeCells( aMergeOption, rDoContents, bRecord, bApi );
1096 if (bOk)
1098 SetCursor( nStartCol, nStartRow );
1099 //DoneBlockMode( sal_False);
1100 Unmark();
1102 pDocSh->UpdateOle(&GetViewData());
1103 UpdateInputLine();
1107 return bOk;
1110 bool ScViewFunc::TestRemoveMerge()
1112 bool bMerged = false;
1113 ScRange aRange;
1114 if (GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1116 ScDocument* pDoc = GetViewData().GetDocument();
1117 if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
1118 bMerged = true;
1120 return bMerged;
1123 static bool lcl_extendMergeRange(ScCellMergeOption& rOption, const ScRange& rRange)
1125 bool bExtended = false;
1126 if (rOption.mnStartCol > rRange.aStart.Col())
1128 rOption.mnStartCol = rRange.aStart.Col();
1129 bExtended = true;
1131 if (rOption.mnStartRow > rRange.aStart.Row())
1133 rOption.mnStartRow = rRange.aStart.Row();
1134 bExtended = true;
1136 if (rOption.mnEndCol < rRange.aEnd.Col())
1138 rOption.mnEndCol = rRange.aEnd.Col();
1139 bExtended = true;
1141 if (rOption.mnEndRow < rRange.aEnd.Row())
1143 rOption.mnEndRow = rRange.aEnd.Row();
1144 bExtended = true;
1146 return bExtended;
1149 bool ScViewFunc::RemoveMerge( bool bRecord )
1151 ScRange aRange;
1152 ScEditableTester aTester( this );
1153 if (!aTester.IsEditable())
1155 ErrorMessage(aTester.GetMessageId());
1156 return false;
1158 else if (GetViewData().GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1160 ScDocument* pDoc = GetViewData().GetDocument();
1161 ScRange aExtended( aRange );
1162 pDoc->ExtendMerge( aExtended );
1163 ScDocShell* pDocSh = GetViewData().GetDocShell();
1164 const ScMarkData& rMark = GetViewData().GetMarkData();
1165 ScCellMergeOption aOption(aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row());
1166 bool bExtended = false;
1169 bExtended = false;
1170 ScMarkData::const_iterator itr = rMark.begin(), itrEnd = rMark.end();
1171 for (; itr != itrEnd; ++itr)
1173 SCTAB i = *itr;
1174 aOption.maTabs.insert(i);
1175 aExtended.aStart.SetTab(i);
1176 aExtended.aEnd.SetTab(i);
1177 pDoc->ExtendMerge(aExtended);
1178 pDoc->ExtendOverlapped(aExtended);
1180 // Expand the current range to be inclusive of all merged
1181 // areas on all sheets.
1182 bExtended = lcl_extendMergeRange(aOption, aExtended);
1185 while (bExtended);
1187 bool bOk = pDocSh->GetDocFunc().UnmergeCells(aOption, bRecord );
1188 aExtended = aOption.getFirstSingleRange();
1189 MarkRange( aExtended );
1191 if (bOk)
1192 pDocSh->UpdateOle(&GetViewData());
1194 return true; //! bOk ??
1197 void ScViewFunc::FillSimple( FillDir eDir, bool bRecord )
1199 ScRange aRange;
1200 if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1202 ScDocShell* pDocSh = GetViewData().GetDocShell();
1203 const ScMarkData& rMark = GetViewData().GetMarkData();
1204 bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, false );
1205 if (bSuccess)
1207 pDocSh->UpdateOle(&GetViewData());
1208 UpdateScrollBars();
1209 bool bDoAutoSpell = pDocSh->GetDocument().GetDocOptions().IsAutoSpell();
1210 if ( bDoAutoSpell )
1211 CopyAutoSpellData(eDir, aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(),
1212 ::std::numeric_limits<sal_uLong>::max());
1215 else
1216 ErrorMessage(STR_NOMULTISELECT);
1219 void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
1220 double fStart, double fStep, double fMax, bool bRecord )
1222 ScRange aRange;
1223 if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1225 ScDocShell* pDocSh = GetViewData().GetDocShell();
1226 const ScMarkData& rMark = GetViewData().GetMarkData();
1227 bool bSuccess = pDocSh->GetDocFunc().
1228 FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd,
1229 fStart, fStep, fMax, bRecord, false );
1230 if (bSuccess)
1232 pDocSh->UpdateOle(&GetViewData());
1233 UpdateScrollBars();
1235 HelperNotifyChanges::NotifyIfChangesListeners(*pDocSh, aRange);
1238 else
1239 ErrorMessage(STR_NOMULTISELECT);
1242 void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
1243 SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, bool bRecord )
1245 SCTAB nTab = GetViewData().GetTabNo();
1246 ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab );
1247 ScRange aSourceRange( aRange );
1248 ScDocShell* pDocSh = GetViewData().GetDocShell();
1249 const ScMarkData& rMark = GetViewData().GetMarkData();
1250 bool bSuccess = pDocSh->GetDocFunc().
1251 FillAuto( aRange, &rMark, eDir, nCount, bRecord, false );
1252 if (bSuccess)
1254 MarkRange( aRange, false ); // aRange was modified in FillAuto
1255 pDocSh->UpdateOle(&GetViewData());
1256 UpdateScrollBars();
1258 bool bDoAutoSpell = pDocSh->GetDocument().GetDocOptions().IsAutoSpell();
1259 if ( bDoAutoSpell )
1260 CopyAutoSpellData(eDir, nStartCol, nStartRow, nEndCol, nEndRow, nCount);
1262 if (ScModelObj* pModelObj = HelperNotifyChanges::getMustPropagateChangesModel(*pDocSh))
1264 ScRangeList aChangeRanges;
1265 ScRange aChangeRange( aRange );
1266 switch (eDir)
1268 case FILL_TO_BOTTOM:
1269 aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 );
1270 break;
1271 case FILL_TO_TOP:
1272 aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 );
1273 break;
1274 case FILL_TO_RIGHT:
1275 aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 );
1276 break;
1277 case FILL_TO_LEFT:
1278 aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 );
1279 break;
1280 default:
1281 break;
1283 aChangeRanges.Append( aChangeRange );
1284 HelperNotifyChanges::Notify(*pModelObj, aChangeRanges);
1289 void ScViewFunc::CopyAutoSpellData( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
1290 SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount )
1292 ScGridWindow* pWin = this->GetActiveWin();
1293 if ( pWin->InsideVisibleRange(nStartCol, nStartRow) && pWin->InsideVisibleRange(nEndCol, nEndRow) )
1295 if ( nCount == ::std::numeric_limits<sal_uLong>::max() )
1297 switch( eDir )
1299 case FILL_TO_BOTTOM:
1300 for ( SCCOL nColItr = nStartCol; nColItr <= nEndCol; ++nColItr )
1302 const std::vector<editeng::MisspellRanges>* pRanges = pWin->GetAutoSpellData(nColItr, nStartRow);
1303 if ( !pRanges )
1304 continue;
1305 for ( SCROW nRowItr = nStartRow + 1; nRowItr <= nEndRow; ++nRowItr )
1306 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1308 break;
1309 case FILL_TO_TOP:
1310 for ( SCCOL nColItr = nStartCol; nColItr <= nEndCol; ++nColItr )
1312 const std::vector<editeng::MisspellRanges>* pRanges = pWin->GetAutoSpellData(nColItr, nEndRow);
1313 if ( !pRanges )
1314 continue;
1315 for ( SCROW nRowItr = nEndRow - 1; nRowItr >= nStartRow; --nRowItr )
1316 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1318 break;
1319 case FILL_TO_RIGHT:
1320 for ( SCROW nRowItr = nStartRow; nRowItr <= nEndRow; ++nRowItr )
1322 const std::vector<editeng::MisspellRanges>* pRanges = pWin->GetAutoSpellData(nStartCol, nRowItr);
1323 if ( !pRanges )
1324 continue;
1325 for ( SCCOL nColItr = nStartCol + 1; nColItr <= nEndCol; ++nColItr )
1326 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1328 break;
1329 case FILL_TO_LEFT:
1330 for ( SCROW nRowItr = nStartRow; nRowItr <= nEndRow; ++nRowItr )
1332 const std::vector<editeng::MisspellRanges>* pRanges = pWin->GetAutoSpellData(nEndCol, nRowItr);
1333 if ( !pRanges )
1334 continue;
1335 for ( SCCOL nColItr = nEndCol - 1; nColItr >= nStartCol; --nColItr )
1336 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1338 break;
1340 return;
1343 typedef const std::vector<editeng::MisspellRanges>* MisspellRangesType;
1344 SCROW nRowRepeatSize = (nEndRow - nStartRow + 1);
1345 SCCOL nColRepeatSize = (nEndCol - nStartCol + 1);
1346 SCROW nTillRow = 0;
1347 SCCOL nTillCol = 0;
1348 std::vector<std::vector<MisspellRangesType>> aSourceSpellRanges(nRowRepeatSize, std::vector<MisspellRangesType>(nColRepeatSize));
1350 for ( SCROW nRowIdx = 0; nRowIdx < nRowRepeatSize; ++nRowIdx )
1351 for ( SCROW nColIdx = 0; nColIdx < nColRepeatSize; ++nColIdx )
1352 aSourceSpellRanges[nRowIdx][nColIdx] = pWin->GetAutoSpellData( nStartCol + nColIdx, nStartRow + nRowIdx );
1354 switch( eDir )
1356 case FILL_TO_BOTTOM:
1357 nTillRow = nEndRow + nCount;
1358 for ( SCCOL nColItr = nStartCol; nColItr <= nEndCol; ++nColItr )
1360 for ( SCROW nRowItr = nEndRow + 1; nRowItr <= nTillRow; ++nRowItr )
1362 size_t nSourceRowIdx = ( ( nRowItr - nEndRow - 1 ) % nRowRepeatSize );
1363 MisspellRangesType pRanges = aSourceSpellRanges[nSourceRowIdx][nColItr - nStartCol];
1364 if ( !pRanges )
1365 continue;
1366 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1369 break;
1371 case FILL_TO_TOP:
1372 nTillRow = nStartRow - nCount;
1373 for ( SCCOL nColItr = nStartCol; nColItr <= nEndCol; ++nColItr )
1375 for ( SCROW nRowItr = nStartRow - 1; nRowItr >= nTillRow; --nRowItr )
1377 size_t nSourceRowIdx = nRowRepeatSize - 1 - ( ( nStartRow - 1 - nRowItr ) % nRowRepeatSize );
1378 MisspellRangesType pRanges = aSourceSpellRanges[nSourceRowIdx][nColItr - nStartCol];
1379 if ( !pRanges )
1380 continue;
1381 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1384 break;
1386 case FILL_TO_RIGHT:
1387 nTillCol = nEndCol + nCount;
1388 for ( SCCOL nColItr = nEndCol + 1; nColItr <= nTillCol; ++nColItr )
1390 size_t nSourceColIdx = ( ( nColItr - nEndCol - 1 ) % nColRepeatSize );
1391 for ( SCROW nRowItr = nStartRow; nRowItr <= nEndRow; ++nRowItr )
1393 MisspellRangesType pRanges = aSourceSpellRanges[nRowItr - nStartRow][nSourceColIdx];
1394 if ( !pRanges )
1395 continue;
1396 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1399 break;
1401 case FILL_TO_LEFT:
1402 nTillCol = nStartCol - nCount;
1403 for ( SCCOL nColItr = nStartCol - 1; nColItr >= nTillCol; --nColItr )
1405 size_t nSourceColIdx = nColRepeatSize - 1 - ( ( nStartCol - 1 - nColItr ) % nColRepeatSize );
1406 for ( SCROW nRowItr = nStartRow; nRowItr <= nEndRow; ++nRowItr )
1408 MisspellRangesType pRanges = aSourceSpellRanges[nRowItr - nStartRow][nSourceColIdx];
1409 if ( !pRanges )
1410 continue;
1411 pWin->SetAutoSpellData(nColItr, nRowItr, pRanges);
1414 break;
1417 else
1418 pWin->ResetAutoSpell();
1422 void ScViewFunc::FillTab( InsertDeleteFlags nFlags, sal_uInt16 nFunction, bool bSkipEmpty, bool bAsLink )
1424 //! allow source sheet to be protected
1425 ScEditableTester aTester( this );
1426 if (!aTester.IsEditable())
1428 ErrorMessage(aTester.GetMessageId());
1429 return;
1432 ScDocShell* pDocSh = GetViewData().GetDocShell();
1433 ScDocument& rDoc = pDocSh->GetDocument();
1434 ScMarkData& rMark = GetViewData().GetMarkData();
1435 SCTAB nTab = GetViewData().GetTabNo();
1436 bool bUndo(rDoc.IsUndoEnabled());
1438 ScRange aMarkRange;
1439 rMark.MarkToSimple();
1440 bool bMulti = rMark.IsMultiMarked();
1441 if (bMulti)
1442 rMark.GetMultiMarkArea( aMarkRange );
1443 else if (rMark.IsMarked())
1444 rMark.GetMarkArea( aMarkRange );
1445 else
1446 aMarkRange = ScRange( GetViewData().GetCurX(), GetViewData().GetCurY(), nTab );
1448 ScDocument* pUndoDoc = NULL;
1450 if (bUndo)
1452 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1453 pUndoDoc->InitUndo( &rDoc, nTab, nTab );
1455 ScMarkData::iterator itr = rMark.begin(), itrEnd = rMark.end();
1456 for (; itr != itrEnd; ++itr)
1457 if (*itr != nTab )
1459 SCTAB i = *itr;
1460 pUndoDoc->AddUndoTab( i, i );
1461 aMarkRange.aStart.SetTab( i );
1462 aMarkRange.aEnd.SetTab( i );
1463 rDoc.CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc );
1467 if (bMulti)
1468 rDoc.FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1469 else
1471 aMarkRange.aStart.SetTab( nTab );
1472 aMarkRange.aEnd.SetTab( nTab );
1473 rDoc.FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1476 if (bUndo)
1477 { //! for ChangeTrack not until the end
1478 pDocSh->GetUndoManager()->AddUndoAction(
1479 new ScUndoFillTable( pDocSh, rMark,
1480 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab,
1481 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab,
1482 pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) );
1485 pDocSh->PostPaintGridAll();
1486 pDocSh->PostDataChanged();
1489 /** Downward fill of selected cell(s) by double-clicking cross-hair cursor
1491 Extends a current selection down to the last non-empty cell of an adjacent
1492 column when the lower-right corner of the selection is double-clicked. It
1493 uses a left-adjoining non-empty column as a guide if such is available,
1494 otherwise a right-adjoining non-empty column is used.
1496 @author Kohei Yoshida (kohei@openoffice.org)
1498 @return No return value
1500 @see #i12313#
1502 void ScViewFunc::FillCrossDblClick()
1504 ScRange aRange;
1505 GetViewData().GetSimpleArea( aRange );
1506 aRange.Justify();
1508 SCTAB nTab = GetViewData().GetCurPos().Tab();
1509 SCCOL nStartX = aRange.aStart.Col();
1510 SCROW nStartY = aRange.aStart.Row();
1511 SCCOL nEndX = aRange.aEnd.Col();
1512 SCROW nEndY = aRange.aEnd.Row();
1514 ScDocument* pDoc = GetViewData().GetDocument();
1516 // Make sure the selection is not empty
1517 if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) )
1518 return;
1520 if ( nEndY < MAXROW )
1522 if ( nStartX > 0 )
1524 SCCOL nMovX = nStartX - 1;
1525 SCROW nMovY = nStartY;
1527 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1528 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1530 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1532 if ( nMovY > nEndY )
1534 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1535 nMovY - nEndY );
1536 return;
1541 if ( nEndX < MAXCOL )
1543 SCCOL nMovX = nEndX + 1;
1544 SCROW nMovY = nStartY;
1546 if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1547 pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1549 pDoc->FindAreaPos( nMovX, nMovY, nTab, SC_MOVE_DOWN );
1551 if ( nMovY > nEndY )
1553 FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1554 nMovY - nEndY );
1555 return;
1562 void ScViewFunc::ConvertFormulaToValue()
1564 ScRange aRange;
1565 GetViewData().GetSimpleArea(aRange);
1566 aRange.Justify();
1568 ScDocShell* pDocSh = GetViewData().GetDocShell();
1569 pDocSh->GetDocFunc().ConvertFormulaToValue(aRange, true, true);
1570 pDocSh->PostPaint(aRange, PAINT_GRID);
1573 void ScViewFunc::TransliterateText( sal_Int32 nType )
1575 ScMarkData aFuncMark = GetViewData().GetMarkData();
1576 if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1578 // no selection -> use cursor position
1580 ScAddress aCursor( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().GetTabNo() );
1581 aFuncMark.SetMarkArea( ScRange( aCursor ) );
1584 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().
1585 TransliterateText( aFuncMark, nType, true, false );
1586 if (bSuccess)
1588 GetViewData().GetViewShell()->UpdateInputHandler();
1592 // AutoFormat
1594 ScAutoFormatData* ScViewFunc::CreateAutoFormatData()
1596 ScAutoFormatData* pData = NULL;
1597 SCCOL nStartCol;
1598 SCROW nStartRow;
1599 SCTAB nStartTab;
1600 SCCOL nEndCol;
1601 SCROW nEndRow;
1602 SCTAB nEndTab;
1603 if (GetViewData().GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1605 if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 )
1607 ScDocument* pDoc = GetViewData().GetDocument();
1608 pData = new ScAutoFormatData;
1609 pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData );
1612 return pData;
1615 void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, bool bRecord )
1617 ScRange aRange;
1618 if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1620 ScDocShell* pDocSh = GetViewData().GetDocShell();
1621 ScMarkData& rMark = GetViewData().GetMarkData();
1623 bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, false );
1624 if (bSuccess)
1625 pDocSh->UpdateOle(&GetViewData());
1627 else
1628 ErrorMessage(STR_NOMULTISELECT);
1631 // Suchen & Ersetzen
1633 bool ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem,
1634 bool bAddUndo, bool bIsApi )
1636 SvxSearchDialogWrapper::SetSearchLabel(SL_Empty);
1637 ScDocShell* pDocSh = GetViewData().GetDocShell();
1638 ScDocument& rDoc = pDocSh->GetDocument();
1639 ScMarkData& rMark = GetViewData().GetMarkData();
1640 if (bAddUndo && !rDoc.IsUndoEnabled())
1641 bAddUndo = false;
1643 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() && (pSearchItem->HasStartPoint()) )
1645 // No selection -> but we have a start point (top left corner of the
1646 // current view), start searching from there, not from the current
1647 // cursor position.
1648 SCsCOL nPosX;
1649 SCsROW nPosY;
1651 int nPixelX = pSearchItem->GetStartPointX() * GetViewData().GetPPTX();
1652 int nPixelY = pSearchItem->GetStartPointY() * GetViewData().GetPPTY();
1654 GetViewData().GetPosFromPixel(nPixelX, nPixelY, GetViewData().GetActivePart(), nPosX, nPosY);
1656 AlignToCursor( nPosX, nPosY, SC_FOLLOW_JUMP );
1657 SetCursor( nPosX, nPosY, true );
1660 SCCOL nCol, nOldCol;
1661 SCROW nRow, nOldRow;
1662 SCTAB nTab, nOldTab;
1663 nCol = nOldCol = GetViewData().GetCurX();
1664 nRow = nOldRow = GetViewData().GetCurY();
1665 nTab = nOldTab = GetViewData().GetTabNo();
1667 SvxSearchCmd nCommand = pSearchItem->GetCommand();
1668 bool bAllTables = pSearchItem->IsAllTables();
1669 std::set<SCTAB> aOldSelectedTables;
1670 SCTAB nLastTab = rDoc.GetTableCount() - 1;
1671 SCTAB nStartTab, nEndTab;
1672 if ( bAllTables )
1674 nStartTab = 0;
1675 nEndTab = nLastTab;
1676 std::set<SCTAB> aTmp(rMark.begin(), rMark.end());
1677 aOldSelectedTables.swap(aTmp);
1679 else
1680 { //! at least one is always selected
1681 nStartTab = rMark.GetFirstSelected();
1682 nEndTab = rMark.GetLastSelected();
1685 if ( nCommand == SvxSearchCmd::FIND
1686 || nCommand == SvxSearchCmd::FIND_ALL)
1687 bAddUndo = false;
1689 //! account for bAttrib during Undo !!!
1691 std::unique_ptr<ScDocument> pUndoDoc;
1692 std::unique_ptr<ScMarkData> pUndoMark;
1693 OUString aUndoStr;
1694 if (bAddUndo)
1696 pUndoMark.reset(new ScMarkData(rMark)); // Mark is being modified
1697 if ( nCommand == SvxSearchCmd::REPLACE_ALL )
1699 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1700 pUndoDoc->InitUndo( &rDoc, nStartTab, nEndTab );
1704 if ( bAllTables )
1705 { //! select all, after pUndoMark has been created
1706 for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1708 rMark.SelectTable( j, true );
1712 DoneBlockMode(true); // don't delete mark
1713 InitOwnBlockMode();
1715 // If search starts at the beginning don't ask again whether it shall start at the beginning
1716 bool bFirst = true;
1717 if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward() )
1718 bFirst = false;
1720 bool bFound = false;
1721 while (true)
1723 GetFrameWin()->EnterWait();
1724 ScRangeList aMatchedRanges;
1725 if (rDoc.SearchAndReplace(*pSearchItem, nCol, nRow, nTab, rMark, aMatchedRanges, aUndoStr, pUndoDoc.get()))
1727 bFound = true;
1728 bFirst = true;
1729 if (bAddUndo)
1731 GetViewData().GetDocShell()->GetUndoManager()->AddUndoAction(
1732 new ScUndoReplace( GetViewData().GetDocShell(), *pUndoMark,
1733 nCol, nRow, nTab,
1734 aUndoStr, pUndoDoc.release(), pSearchItem ) );
1737 if (nCommand == SvxSearchCmd::FIND_ALL || nCommand == SvxSearchCmd::REPLACE_ALL)
1739 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1740 if (pViewFrm)
1742 pViewFrm->ShowChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId(), true);
1743 SfxChildWindow* pWnd = pViewFrm->GetChildWindow(sc::SearchResultsDlgWrapper::GetChildWindowId());
1744 if (pWnd)
1746 sc::SearchResultsDlg* pDlg = static_cast<sc::SearchResultsDlg*>(pWnd->GetWindow());
1747 if (pDlg)
1748 pDlg->FillResults(&rDoc, aMatchedRanges);
1752 rMark.ResetMark();
1753 for (size_t i = 0, n = aMatchedRanges.size(); i < n; ++i)
1755 const ScRange& r = *aMatchedRanges[i];
1756 if (r.aStart.Tab() == nTab)
1757 rMark.SetMultiMarkArea(r);
1761 break; // break 'while (TRUE)'
1763 else if ( bFirst && (nCommand == SvxSearchCmd::FIND ||
1764 nCommand == SvxSearchCmd::REPLACE) )
1766 bFirst = false;
1767 GetFrameWin()->LeaveWait();
1768 if (!bIsApi)
1770 if ( nStartTab == nEndTab )
1771 SvxSearchDialogWrapper::SetSearchLabel(SL_EndSheet);
1772 else
1773 SvxSearchDialogWrapper::SetSearchLabel(SL_End);
1775 ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
1776 if (pSearchItem->GetBackward())
1777 nTab = nEndTab;
1778 else
1779 nTab = nStartTab;
1781 else
1783 break; // break 'while (TRUE)'
1786 else // nothing found
1788 if ( nCommand == SvxSearchCmd::FIND_ALL || nCommand == SvxSearchCmd::REPLACE_ALL )
1790 pDocSh->PostPaintGridAll(); // Mark
1793 GetFrameWin()->LeaveWait();
1794 if (!bIsApi)
1796 rDoc.GetDrawLayer()->libreOfficeKitCallback(LOK_CALLBACK_SEARCH_NOT_FOUND,
1797 pSearchItem->GetSearchString().toUtf8().getStr());
1798 SvxSearchDialogWrapper::SetSearchLabel(SL_NotFound);
1801 break; // break 'while (TRUE)'
1803 } // of while true
1805 if (!aOldSelectedTables.empty())
1807 // restore originally selected table
1808 for (SCTAB i = 0; i <= nEndTab; ++i)
1809 rMark.SelectTable(i, false);
1811 std::set<SCTAB>::const_iterator itr = aOldSelectedTables.begin(), itrEnd = aOldSelectedTables.end();
1812 for (; itr != itrEnd; ++itr)
1813 rMark.SelectTable(*itr, true);
1815 if ( bFound )
1816 { // if a table is selected as a "match" it remains selected.
1817 rMark.SelectTable( nTab, true );
1818 // It's a swap if only one table was selected before
1819 //! otherwise now one table more might be selected
1820 if ( aOldSelectedTables.size() == 1 && nTab != nOldTab )
1821 rMark.SelectTable( nOldTab, false );
1825 MarkDataChanged();
1827 if ( bFound )
1829 if ( nTab != GetViewData().GetTabNo() )
1830 SetTabNo( nTab );
1832 // if nothing is marked, DoneBlockMode, then marking can start
1833 // directly from this place via Shift-Cursor
1834 if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1835 DoneBlockMode(true);
1837 AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
1838 SetCursor( nCol, nRow, true );
1840 if (rDoc.GetDrawLayer()->isTiledRendering())
1842 Point aCurPos = GetViewData().GetScrPos(nCol, nRow, GetViewData().GetActivePart());
1844 // just update the cell selection
1845 ScGridWindow* pGridWindow = GetViewData().GetActiveWin();
1846 if (pGridWindow)
1848 // move the cell selection handles
1849 pGridWindow->SetCellSelectionPixel(LOK_SETTEXTSELECTION_RESET, aCurPos.X(), aCurPos.Y());
1850 pGridWindow->SetCellSelectionPixel(LOK_SETTEXTSELECTION_START, aCurPos.X(), aCurPos.Y());
1851 pGridWindow->SetCellSelectionPixel(LOK_SETTEXTSELECTION_END, aCurPos.X(), aCurPos.Y());
1855 if ( nCommand == SvxSearchCmd::REPLACE
1856 || nCommand == SvxSearchCmd::REPLACE_ALL )
1858 if ( nCommand == SvxSearchCmd::REPLACE )
1860 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID );
1862 // jump to next cell if we replaced everything in the cell
1863 // where the cursor was positioned (but avoid switching tabs)
1864 if ( nCol == nOldCol && nRow == nOldRow && nTab == nOldTab )
1866 SvxSearchItem aSearchItem = ScGlobal::GetSearchItem();
1867 aSearchItem.SetCommand(SvxSearchCmd::FIND);
1868 aSearchItem.SetWhich(SID_SEARCH_ITEM);
1870 ScRangeList aMatchedRanges;
1871 ScTable::UpdateSearchItemAddressForReplace( aSearchItem, nCol, nRow );
1872 if ( rDoc.SearchAndReplace( aSearchItem, nCol, nRow, nTab, rMark, aMatchedRanges, aUndoStr, NULL ) &&
1873 ( nTab == nOldTab ) &&
1874 ( nCol != nOldCol || nRow != nOldRow ) )
1876 SetCursor( nCol, nRow, true );
1880 else
1881 pDocSh->PostPaintGridAll();
1882 pDocSh->SetDocumentModified();
1884 else if ( nCommand == SvxSearchCmd::FIND_ALL )
1885 pDocSh->PostPaintGridAll(); // mark
1886 GetFrameWin()->LeaveWait();
1888 return bFound;
1891 // Zielwertsuche
1893 void ScViewFunc::Solve( const ScSolveParam& rParam )
1895 ScDocument* pDoc = GetViewData().GetDocument();
1897 if ( pDoc )
1899 SCCOL nDestCol = rParam.aRefVariableCell.Col();
1900 SCROW nDestRow = rParam.aRefVariableCell.Row();
1901 SCTAB nDestTab = rParam.aRefVariableCell.Tab();
1903 ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow );
1904 if (!aTester.IsEditable())
1906 ErrorMessage(aTester.GetMessageId());
1907 return;
1910 OUString aTargetValStr;
1911 if ( rParam.pStrTargetVal != NULL )
1912 aTargetValStr = *(rParam.pStrTargetVal);
1914 OUString aMsgStr;
1915 OUString aResStr;
1916 double nSolveResult;
1918 GetFrameWin()->EnterWait();
1920 bool bExact =
1921 pDoc->Solver(
1922 rParam.aRefFormulaCell.Col(),
1923 rParam.aRefFormulaCell.Row(),
1924 rParam.aRefFormulaCell.Tab(),
1925 nDestCol, nDestRow, nDestTab,
1926 aTargetValStr,
1927 nSolveResult );
1929 GetFrameWin()->LeaveWait();
1931 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1932 sal_uLong nFormat = 0;
1933 const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab );
1934 if ( pPattern )
1935 nFormat = pPattern->GetNumberFormat( pFormatter );
1936 Color* p;
1937 pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p );
1939 if ( bExact )
1941 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_0 );
1942 aMsgStr += aResStr;
1943 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 );
1945 else
1947 aMsgStr = ScGlobal::GetRscString( STR_MSSG_SOLVE_2 );
1948 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_3 );
1949 aMsgStr += aResStr ;
1950 aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 );
1953 ScopedVclPtrInstance<MessBox> aBox( GetViewData().GetDialogParent(),
1954 WinBits(WB_YES_NO | WB_DEF_NO),
1955 ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr );
1956 sal_uInt16 nRetVal = aBox->Execute();
1958 if ( RET_YES == nRetVal )
1959 EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult );
1961 GetViewData().GetViewShell()->UpdateInputHandler( true );
1965 // multi operation
1967 void ScViewFunc::TabOp( const ScTabOpParam& rParam, bool bRecord )
1969 ScRange aRange;
1970 if (GetViewData().GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1972 ScDocShell* pDocSh = GetViewData().GetDocShell();
1973 ScMarkData& rMark = GetViewData().GetMarkData();
1974 pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, false );
1976 else
1977 ErrorMessage(STR_NOMULTISELECT);
1980 void ScViewFunc::MakeScenario( const OUString& rName, const OUString& rComment,
1981 const Color& rColor, sal_uInt16 nFlags )
1983 ScDocShell* pDocSh = GetViewData().GetDocShell();
1984 ScMarkData& rMark = GetViewData().GetMarkData();
1985 SCTAB nTab = GetViewData().GetTabNo();
1987 SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark );
1988 if (nFlags & SC_SCENARIO_COPYALL)
1989 SetTabNo( nNewTab, true ); // SC_SCENARIO_COPYALL -> visible
1990 else
1992 SfxBindings& rBindings = GetViewData().GetBindings();
1993 rBindings.Invalidate( SID_STATUS_DOCPOS ); // Statusbar
1994 rBindings.Invalidate( SID_ROWCOL_SELCOUNT ); // Statusbar
1995 rBindings.Invalidate( SID_TABLES_COUNT );
1996 rBindings.Invalidate( SID_SELECT_SCENARIO );
1997 rBindings.Invalidate( FID_TABLE_SHOW );
2001 void ScViewFunc::ExtendScenario()
2003 ScEditableTester aTester( this );
2004 if (!aTester.IsEditable())
2006 ErrorMessage(aTester.GetMessageId());
2007 return;
2010 // Undo: apply attributes
2012 ScDocument* pDoc = GetViewData().GetDocument();
2013 ScPatternAttr aPattern( pDoc->GetPool() );
2014 aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
2015 aPattern.GetItemSet().Put( ScProtectionAttr( true ) );
2016 ApplySelectionPattern(aPattern);
2019 void ScViewFunc::UseScenario( const OUString& rName )
2021 ScDocShell* pDocSh = GetViewData().GetDocShell();
2022 SCTAB nTab = GetViewData().GetTabNo();
2024 DoneBlockMode();
2025 InitOwnBlockMode();
2026 pDocSh->UseScenario( nTab, rName );
2029 // Insert table
2031 bool ScViewFunc::InsertTable( const OUString& rName, SCTAB nTab, bool bRecord )
2033 // Order Tabl/Name is inverted for DocFunc
2034 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().
2035 InsertTable( nTab, rName, bRecord, false );
2036 if (bSuccess)
2037 SetTabNo( nTab, true );
2039 return bSuccess;
2042 // Insert tables
2044 bool ScViewFunc::InsertTables(std::vector<OUString>& aNames, SCTAB nTab,
2045 SCTAB nCount, bool bRecord )
2047 ScDocShell* pDocSh = GetViewData().GetDocShell();
2048 ScDocument& rDoc = pDocSh->GetDocument();
2049 if (bRecord && !rDoc.IsUndoEnabled())
2050 bRecord = false;
2052 WaitObject aWait( GetFrameWin() );
2054 if (bRecord)
2056 rDoc.BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
2059 bool bFlag=false;
2061 if(aNames.empty())
2063 rDoc.CreateValidTabNames(aNames, nCount);
2065 if (rDoc.InsertTabs(nTab, aNames, false))
2067 pDocSh->Broadcast( ScTablesHint( SC_TABS_INSERTED, nTab, nCount ) );
2068 bFlag = true;
2071 if (bFlag)
2073 if (bRecord)
2074 pDocSh->GetUndoManager()->AddUndoAction(
2075 new ScUndoInsertTables( pDocSh, nTab, aNames));
2077 // Update views
2079 SetTabNo( nTab, true );
2080 pDocSh->PostPaintExtras();
2081 pDocSh->SetDocumentModified();
2082 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2083 return true;
2085 else
2087 return false;
2091 bool ScViewFunc::AppendTable( const OUString& rName, bool bRecord )
2093 ScDocShell* pDocSh = GetViewData().GetDocShell();
2094 ScDocument& rDoc = pDocSh->GetDocument();
2095 if (bRecord && !rDoc.IsUndoEnabled())
2096 bRecord = false;
2098 WaitObject aWait( GetFrameWin() );
2100 if (bRecord)
2101 rDoc.BeginDrawUndo(); // InsertTab creates a SdrUndoNewPage
2103 if (rDoc.InsertTab( SC_TAB_APPEND, rName ))
2105 SCTAB nTab = rDoc.GetTableCount()-1;
2106 if (bRecord)
2107 pDocSh->GetUndoManager()->AddUndoAction(
2108 new ScUndoInsertTab( pDocSh, nTab, true, rName));
2109 GetViewData().InsertTab( nTab );
2110 SetTabNo( nTab, true );
2111 pDocSh->PostPaintExtras();
2112 pDocSh->SetDocumentModified();
2113 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2114 return true;
2116 else
2118 return false;
2122 bool ScViewFunc::DeleteTable( SCTAB nTab, bool bRecord )
2124 ScDocShell* pDocSh = GetViewData().GetDocShell();
2125 ScDocument& rDoc = pDocSh->GetDocument();
2127 bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, false );
2128 if (bSuccess)
2130 SCTAB nNewTab = nTab;
2131 if ( nNewTab >= rDoc.GetTableCount() )
2132 --nNewTab;
2133 SetTabNo( nNewTab, true );
2135 return bSuccess;
2138 //only use this method for undo for now, all sheets must be connected
2139 //this method doesn't support undo for now, merge it when it with the other method later
2140 bool ScViewFunc::DeleteTables( const SCTAB nTab, SCTAB nSheets )
2142 ScDocShell* pDocSh = GetViewData().GetDocShell();
2143 ScDocument& rDoc = pDocSh->GetDocument();
2144 bool bVbaEnabled = rDoc.IsInVBAMode();
2145 SCTAB nNewTab = nTab;
2146 WaitObject aWait( GetFrameWin() );
2148 while ( nNewTab > 0 && !rDoc.IsVisible( nNewTab ) )
2149 --nNewTab;
2151 if (rDoc.DeleteTabs(nTab, nSheets))
2153 if( bVbaEnabled )
2155 for (SCTAB aTab = 0; aTab < nSheets; ++aTab)
2157 OUString sCodeName;
2158 bool bHasCodeName = rDoc.GetCodeName( nTab + aTab, sCodeName );
2159 if ( bHasCodeName )
2160 VBA_DeleteModule( *pDocSh, sCodeName );
2164 pDocSh->Broadcast( ScTablesHint( SC_TABS_DELETED, nTab, nSheets ) );
2165 if ( nNewTab >= rDoc.GetTableCount() )
2166 nNewTab = rDoc.GetTableCount() - 1;
2167 SetTabNo( nNewTab, true );
2169 pDocSh->PostPaintExtras();
2170 pDocSh->SetDocumentModified();
2172 SfxApplication* pSfxApp = SfxGetpApp(); // Navigator
2173 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2174 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2175 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2176 return true;
2178 return false;
2181 bool ScViewFunc::DeleteTables(const vector<SCTAB> &TheTabs, bool bRecord )
2183 ScDocShell* pDocSh = GetViewData().GetDocShell();
2184 ScDocument& rDoc = pDocSh->GetDocument();
2185 bool bVbaEnabled = rDoc.IsInVBAMode();
2186 SCTAB nNewTab = TheTabs.front();
2187 WaitObject aWait( GetFrameWin() );
2188 if (bRecord && !rDoc.IsUndoEnabled())
2189 bRecord = false;
2190 if ( bVbaEnabled )
2191 bRecord = false;
2193 while ( nNewTab > 0 && !rDoc.IsVisible( nNewTab ) )
2194 --nNewTab;
2196 bool bWasLinked = false;
2197 ScDocument* pUndoDoc = NULL;
2198 ScRefUndoData* pUndoData = NULL;
2199 if (bRecord)
2201 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2202 SCTAB nCount = rDoc.GetTableCount();
2204 OUString aOldName;
2205 for(unsigned int i=0; i<TheTabs.size(); ++i)
2207 SCTAB nTab = TheTabs[i];
2208 if (i==0)
2209 pUndoDoc->InitUndo( &rDoc, nTab,nTab, true,true ); // incl. column/fow flags
2210 else
2211 pUndoDoc->AddUndoTab( nTab,nTab, true,true ); // incl. column/fow flags
2213 rDoc.CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,false, pUndoDoc );
2214 rDoc.GetName( nTab, aOldName );
2215 pUndoDoc->RenameTab( nTab, aOldName, false );
2216 if (rDoc.IsLinked(nTab))
2218 bWasLinked = true;
2219 pUndoDoc->SetLink( nTab, rDoc.GetLinkMode(nTab), rDoc.GetLinkDoc(nTab),
2220 rDoc.GetLinkFlt(nTab), rDoc.GetLinkOpt(nTab),
2221 rDoc.GetLinkTab(nTab),
2222 rDoc.GetLinkRefreshDelay(nTab) );
2224 if ( rDoc.IsScenario(nTab) )
2226 pUndoDoc->SetScenario( nTab, true );
2227 OUString aComment;
2228 Color aColor;
2229 sal_uInt16 nScenFlags;
2230 rDoc.GetScenarioData( nTab, aComment, aColor, nScenFlags );
2231 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2232 bool bActive = rDoc.IsActiveScenario( nTab );
2233 pUndoDoc->SetActiveScenario( nTab, bActive );
2235 pUndoDoc->SetVisible( nTab, rDoc.IsVisible( nTab ) );
2236 pUndoDoc->SetTabBgColor( nTab, rDoc.GetTabBgColor(nTab) );
2237 pUndoDoc->SetSheetEvents( nTab, rDoc.GetSheetEvents( nTab ) );
2238 pUndoDoc->SetLayoutRTL( nTab, rDoc.IsLayoutRTL( nTab ) );
2240 if ( rDoc.IsTabProtected( nTab ) )
2241 pUndoDoc->SetTabProtection(nTab, rDoc.GetTabProtection(nTab));
2243 // Drawing-Layer is responsible for its Undo !!!
2244 // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
2247 pUndoDoc->AddUndoTab( 0, nCount-1 ); // all Tabs for references
2249 rDoc.BeginDrawUndo(); // DeleteTab creates a SdrUndoDelPage
2251 pUndoData = new ScRefUndoData( &rDoc );
2254 bool bDelDone = false;
2256 for(int i=TheTabs.size()-1; i>=0; --i)
2258 OUString sCodeName;
2259 bool bHasCodeName = rDoc.GetCodeName( TheTabs[i], sCodeName );
2260 if (rDoc.DeleteTab(TheTabs[i]))
2262 bDelDone = true;
2263 if( bVbaEnabled )
2265 if( bHasCodeName )
2267 VBA_DeleteModule( *pDocSh, sCodeName );
2270 pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i] ) );
2273 if (bRecord)
2275 pDocSh->GetUndoManager()->AddUndoAction(
2276 new ScUndoDeleteTab( GetViewData().GetDocShell(), TheTabs,
2277 pUndoDoc, pUndoData ));
2280 if (bDelDone)
2282 if ( nNewTab >= rDoc.GetTableCount() )
2283 nNewTab = rDoc.GetTableCount() - 1;
2285 SetTabNo( nNewTab, true );
2287 if (bWasLinked)
2289 pDocSh->UpdateLinks(); // update Link-Manager
2290 GetViewData().GetBindings().Invalidate(SID_LINKS);
2293 pDocSh->PostPaintExtras();
2294 pDocSh->SetDocumentModified();
2296 SfxApplication* pSfxApp = SfxGetpApp(); // Navigator
2297 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2298 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2299 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2301 else
2303 delete pUndoDoc;
2304 delete pUndoData;
2306 return bDelDone;
2309 bool ScViewFunc::RenameTable( const OUString& rName, SCTAB nTab )
2311 // order Table/Name is inverted for DocFunc
2312 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().
2313 RenameTable( nTab, rName, true, false );
2314 if (bSuccess)
2316 // the table name might be part of a formula
2317 GetViewData().GetViewShell()->UpdateInputHandler();
2319 return bSuccess;
2322 bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab )
2324 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, true, false );
2325 if (bSuccess)
2327 GetViewData().GetViewShell()->UpdateInputHandler();
2329 return bSuccess;
2332 bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList )
2334 bool bSuccess = GetViewData().GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, true, false );
2335 if (bSuccess)
2337 GetViewData().GetViewShell()->UpdateInputHandler();
2339 return bSuccess;
2342 void ScViewFunc::InsertAreaLink( const OUString& rFile,
2343 const OUString& rFilter, const OUString& rOptions,
2344 const OUString& rSource, sal_uLong nRefresh )
2346 ScDocShell* pDocSh = GetViewData().GetDocShell();
2347 SCCOL nPosX = GetViewData().GetCurX();
2348 SCROW nPosY = GetViewData().GetCurY();
2349 SCTAB nTab = GetViewData().GetTabNo();
2350 ScAddress aPos( nPosX, nPosY, nTab );
2352 pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, false, false );
2355 void ScViewFunc::InsertTableLink( const OUString& rFile,
2356 const OUString& rFilter, const OUString& rOptions,
2357 const OUString& rTabName )
2359 OUString aFilterName = rFilter;
2360 OUString aOpt = rOptions;
2361 OUString aURL = rFile;
2362 ScDocumentLoader aLoader( aURL, aFilterName, aOpt );
2363 if (!aLoader.IsError())
2365 ScDocShell* pSrcSh = aLoader.GetDocShell();
2366 ScDocument& rSrcDoc = pSrcSh->GetDocument();
2367 SCTAB nTab = MAXTAB+1;
2368 if (rTabName.isEmpty()) // no name given -> first table
2369 nTab = 0;
2370 else
2372 OUString aTemp;
2373 SCTAB nCount = rSrcDoc.GetTableCount();
2374 for (SCTAB i=0; i<nCount; i++)
2376 rSrcDoc.GetName( i, aTemp );
2377 if ( aTemp.equals(rTabName) )
2378 nTab = i;
2382 if ( nTab <= MAXTAB )
2383 ImportTables( pSrcSh, 1, &nTab, true,
2384 GetViewData().GetTabNo() );
2388 // Copy/link tables from another document
2390 void ScViewFunc::ImportTables( ScDocShell* pSrcShell,
2391 SCTAB nCount, const SCTAB* pSrcTabs, bool bLink,SCTAB nTab )
2393 ScDocument& rSrcDoc = pSrcShell->GetDocument();
2395 ScDocShell* pDocSh = GetViewData().GetDocShell();
2396 ScDocument& rDoc = pDocSh->GetDocument();
2397 bool bUndo(rDoc.IsUndoEnabled());
2399 bool bError = false;
2400 bool bRefs = false;
2401 bool bName = false;
2403 if (rSrcDoc.GetDrawLayer())
2404 pDocSh->MakeDrawLayer();
2406 if (bUndo)
2407 rDoc.BeginDrawUndo(); // drawing layer must do its own undo actions
2409 SCTAB nInsCount = 0;
2410 SCTAB i;
2411 for( i=0; i<nCount; i++ )
2412 { // insert sheets first and update all references
2413 OUString aName;
2414 rSrcDoc.GetName( pSrcTabs[i], aName );
2415 rDoc.CreateValidTabName( aName );
2416 if ( !rDoc.InsertTab( nTab+i, aName ) )
2418 bError = true; // total error
2419 break; // for
2421 ++nInsCount;
2423 for (i=0; i<nCount && !bError; i++)
2425 SCTAB nSrcTab = pSrcTabs[i];
2426 SCTAB nDestTab1=nTab+i;
2427 sal_uLong nErrVal = pDocSh->TransferTab( *pSrcShell, nSrcTab, nDestTab1,
2428 false, false ); // no insert
2430 switch (nErrVal)
2432 case 0: // internal error or full of errors
2433 bError = true;
2434 break;
2435 case 2:
2436 bRefs = true;
2437 break;
2438 case 3:
2439 bName = true;
2440 break;
2441 case 4:
2442 bRefs = bName = true;
2443 break;
2448 if (bLink)
2450 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
2452 SfxMedium* pMed = pSrcShell->GetMedium();
2453 OUString aFileName = pMed->GetName();
2454 OUString aFilterName;
2455 if (pMed->GetFilter())
2456 aFilterName = pMed->GetFilter()->GetFilterName();
2457 OUString aOptions = ScDocumentLoader::GetOptions(*pMed);
2459 bool bWasThere = rDoc.HasLink( aFileName, aFilterName, aOptions );
2461 sal_uLong nRefresh = 0;
2462 OUString aTabStr;
2463 for (i=0; i<nInsCount; i++)
2465 rSrcDoc.GetName( pSrcTabs[i], aTabStr );
2466 rDoc.SetLink( nTab+i, SC_LINK_NORMAL,
2467 aFileName, aFilterName, aOptions, aTabStr, nRefresh );
2470 if (!bWasThere) // Insert link only once per source document
2472 ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh );
2473 pLink->SetInCreate( true );
2474 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName );
2475 pLink->Update();
2476 pLink->SetInCreate( false );
2478 SfxBindings& rBindings = GetViewData().GetBindings();
2479 rBindings.Invalidate( SID_LINKS );
2483 if (bUndo)
2485 pDocSh->GetUndoManager()->AddUndoAction(
2486 new ScUndoImportTab( pDocSh, nTab, nCount ) );
2489 for (i=0; i<nInsCount; i++)
2490 GetViewData().InsertTab(nTab);
2491 SetTabNo(nTab,true);
2492 pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2493 PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
2495 SfxApplication* pSfxApp = SfxGetpApp();
2496 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2497 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2499 pDocSh->PostPaintExtras();
2500 pDocSh->PostPaintGridAll();
2501 pDocSh->SetDocumentModified();
2503 if (bRefs)
2504 ErrorMessage(STR_ABSREFLOST);
2505 if (bName)
2506 ErrorMessage(STR_NAMECONFLICT);
2509 // Move/Copy table to another document
2511 void ScViewFunc::MoveTable(
2512 sal_uInt16 nDestDocNo, SCTAB nDestTab, bool bCopy, const OUString* pNewTabName )
2514 ScDocument* pDoc = GetViewData().GetDocument();
2515 ScDocShell* pDocShell = GetViewData().GetDocShell();
2516 ScDocument* pDestDoc = NULL;
2517 ScDocShell* pDestShell = NULL;
2518 ScTabViewShell* pDestViewSh = NULL;
2519 bool bUndo (pDoc->IsUndoEnabled());
2520 bool bRename = pNewTabName && !pNewTabName->isEmpty();
2522 bool bNewDoc = (nDestDocNo == SC_DOC_NEW);
2523 if ( bNewDoc )
2525 nDestTab = 0; // firstly insert
2527 // execute without SfxCallMode::RECORD, because already contained in move command
2529 OUString aUrl("private:factory/" STRING_SCAPP);
2530 SfxStringItem aItem( SID_FILE_NAME, aUrl );
2531 SfxStringItem aTarget( SID_TARGETNAME, OUString("_blank") );
2533 const SfxPoolItem* pRetItem = GetViewData().GetDispatcher().Execute(
2534 SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON, &aItem, &aTarget, 0L );
2535 if ( pRetItem )
2537 if ( pRetItem->ISA( SfxObjectItem ) )
2538 pDestShell = PTR_CAST( ScDocShell, static_cast<const SfxObjectItem*>(pRetItem)->GetShell() );
2539 else if ( pRetItem->ISA( SfxViewFrameItem ) )
2541 SfxViewFrame* pFrm = static_cast<const SfxViewFrameItem*>(pRetItem)->GetFrame();
2542 if (pFrm)
2543 pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() );
2545 if (pDestShell)
2546 pDestViewSh = pDestShell->GetBestViewShell();
2549 else
2550 pDestShell = ScDocShell::GetShellByNum( nDestDocNo );
2552 if (!pDestShell)
2554 OSL_FAIL("Dest-Doc nicht gefunden !!!");
2555 return;
2558 ScMarkData& rMark = GetViewData().GetMarkData();
2559 if (bRename && rMark.GetSelectCount() != 1)
2561 // Custom sheet name is provided, but more than one sheet is selected.
2562 // We don't support this scenario at the moment.
2563 return;
2566 pDestDoc = &pDestShell->GetDocument();
2568 SCTAB nTab = GetViewData().GetTabNo();
2570 if (pDestDoc != pDoc)
2572 if (bNewDoc)
2574 while (pDestDoc->GetTableCount() > 1)
2575 pDestDoc->DeleteTab(0);
2576 pDestDoc->RenameTab( 0, OUString("______42_____"),
2577 false );
2580 SCTAB nTabCount = pDoc->GetTableCount();
2581 SCTAB nTabSelCount = rMark.GetSelectCount();
2583 vector<SCTAB> TheTabs;
2585 for(SCTAB i=0; i<nTabCount; ++i)
2587 if(rMark.GetTableSelect(i))
2589 OUString aTabName;
2590 pDoc->GetName( i, aTabName);
2591 TheTabs.push_back(i);
2592 for(SCTAB j=i+1;j<nTabCount;j++)
2594 if((!pDoc->IsVisible(j)) && pDoc->IsScenario(j))
2596 pDoc->GetName( j, aTabName);
2597 TheTabs.push_back(j);
2598 i=j;
2600 else break;
2605 GetFrameWin()->EnterWait();
2607 if (pDoc->GetDrawLayer())
2608 pDestShell->MakeDrawLayer();
2610 if (!bNewDoc && bUndo)
2611 pDestDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2613 sal_uLong nErrVal =1;
2614 if(nDestTab==SC_TAB_APPEND)
2615 nDestTab=pDestDoc->GetTableCount();
2616 SCTAB nDestTab1=nDestTab;
2617 ScClipParam aParam;
2618 for( sal_uInt16 j=0; j<TheTabs.size(); ++j, ++nDestTab1 )
2619 { // insert sheets first and update all references
2620 OUString aName;
2621 if (bRename)
2622 aName = *pNewTabName;
2623 else
2624 pDoc->GetName( TheTabs[j], aName );
2626 pDestDoc->CreateValidTabName( aName );
2627 if ( !pDestDoc->InsertTab( nDestTab1, aName ) )
2629 nErrVal = 0; // total error
2630 break; // for
2632 ScRange aRange( 0, 0, TheTabs[j], MAXCOL, MAXROW, TheTabs[j] );
2633 aParam.maRanges.Append(aRange);
2635 pDoc->SetClipParam(aParam);
2636 if ( nErrVal > 0 )
2638 nDestTab1 = nDestTab;
2639 for(sal_uInt16 i=0; i<TheTabs.size();++i)
2641 nErrVal = pDestShell->TransferTab( *pDocShell, TheTabs[i], static_cast<SCTAB>(nDestTab1), false, false );
2642 nDestTab1++;
2645 OUString sName;
2646 if (!bNewDoc && bUndo)
2648 pDestDoc->GetName(nDestTab, sName);
2649 pDestShell->GetUndoManager()->AddUndoAction(
2650 new ScUndoImportTab( pDestShell, nDestTab,
2651 static_cast<SCTAB>(TheTabs.size())));
2654 else
2656 pDestShell->GetUndoManager()->Clear();
2659 GetFrameWin()->LeaveWait();
2660 switch (nErrVal)
2662 case 0: // internal error or full of errors
2664 ErrorMessage(STR_TABINSERT_ERROR);
2665 return;
2667 case 2:
2668 ErrorMessage(STR_ABSREFLOST);
2669 break;
2670 case 3:
2671 ErrorMessage(STR_NAMECONFLICT);
2672 break;
2673 case 4:
2675 ErrorMessage(STR_ABSREFLOST);
2676 ErrorMessage(STR_NAMECONFLICT);
2678 break;
2679 default:
2680 break;
2683 if (!bCopy)
2685 if(nTabCount!=nTabSelCount)
2686 DeleteTables(TheTabs); // incl. Paint & Undo
2687 else
2688 ErrorMessage(STR_TABREMOVE_ERROR);
2691 if (bNewDoc)
2693 // ChartListenerCollection must be updated before DeleteTab
2694 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
2695 pDestDoc->UpdateChartListenerCollection();
2697 pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size())); // old first table
2698 if (pDestViewSh)
2700 // Make sure to clear the cached page view after sheet
2701 // deletion, which still points to the sdr page belonging to
2702 // the deleted sheet.
2703 SdrView* pSdrView = pDestViewSh->GetSdrView();
2704 if (pSdrView)
2705 pSdrView->ClearPageView();
2707 pDestViewSh->TabChanged(); // Pages auf dem Drawing-Layer
2709 pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2710 PAINT_GRID | PAINT_TOP | PAINT_LEFT |
2711 PAINT_EXTRAS | PAINT_SIZE );
2712 // PAINT_SIZE for outline
2714 else
2716 pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) );
2717 pDestShell->PostPaintExtras();
2718 pDestShell->PostPaintGridAll();
2721 TheTabs.clear();
2723 pDestShell->SetDocumentModified();
2724 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2726 else
2728 // Move or copy within the same document.
2729 SCTAB nTabCount = pDoc->GetTableCount();
2731 unique_ptr< vector<SCTAB> > pSrcTabs(new vector<SCTAB>);
2732 unique_ptr< vector<SCTAB> > pDestTabs(new vector<SCTAB>);
2733 unique_ptr< vector<OUString> > pTabNames(new vector<OUString>);
2734 unique_ptr< vector<OUString> > pDestNames;
2735 pSrcTabs->reserve(nTabCount);
2736 pDestTabs->reserve(nTabCount);
2737 pTabNames->reserve(nTabCount);
2738 OUString aDestName;
2740 for(SCTAB i=0;i<nTabCount;i++)
2742 if(rMark.GetTableSelect(i))
2744 OUString aTabName;
2745 pDoc->GetName( i, aTabName);
2746 pTabNames->push_back(aTabName);
2748 for(SCTAB j=i+1;j<nTabCount;j++)
2750 if((!pDoc->IsVisible(j)) && pDoc->IsScenario(j))
2752 pDoc->GetName( j, aTabName);
2753 pTabNames->push_back(aTabName);
2754 i=j;
2756 else break;
2761 if (bCopy && bUndo)
2762 pDoc->BeginDrawUndo(); // drawing layer must do its own undo actions
2764 pDoc->GetName( nDestTab, aDestName);
2765 SCTAB nDestTab1=nDestTab;
2766 SCTAB nMovTab=0;
2767 for (size_t j = 0, n = pTabNames->size(); j < n; ++j)
2769 nTabCount = pDoc->GetTableCount();
2770 const OUString& rStr = (*pTabNames)[j];
2771 if(!pDoc->GetTable(rStr,nMovTab))
2773 nMovTab=nTabCount;
2775 if(!pDoc->GetTable(aDestName,nDestTab1))
2777 nDestTab1=nTabCount;
2779 pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, false ); // Undo is here
2781 if(bCopy && pDoc->IsScenario(nMovTab))
2783 OUString aComment;
2784 Color aColor;
2785 sal_uInt16 nFlags;
2787 pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags);
2788 pDoc->SetScenario(nDestTab1,true);
2789 pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags);
2790 bool bActive = pDoc->IsActiveScenario(nMovTab );
2791 pDoc->SetActiveScenario( nDestTab1, bActive );
2792 bool bVisible=pDoc->IsVisible(nMovTab);
2793 pDoc->SetVisible(nDestTab1,bVisible );
2796 pSrcTabs->push_back(nMovTab);
2798 if(!bCopy)
2800 if(!pDoc->GetTable(rStr,nDestTab1))
2802 nDestTab1=nTabCount;
2806 pDestTabs->push_back(nDestTab1);
2809 // Rename must be done after all sheets have been moved.
2810 if (bRename)
2812 pDestNames.reset(new vector<OUString>);
2813 size_t n = pDestTabs->size();
2814 pDestNames->reserve(n);
2815 for (size_t j = 0; j < n; ++j)
2817 SCTAB nRenameTab = (*pDestTabs)[j];
2818 OUString aTabName = *pNewTabName;
2819 pDoc->CreateValidTabName( aTabName );
2820 pDestNames->push_back(aTabName);
2821 pDoc->RenameTab(nRenameTab, aTabName);
2824 else
2825 // No need to keep this around when we are not renaming.
2826 pTabNames.reset();
2828 nTab = GetViewData().GetTabNo();
2830 if (bUndo)
2832 if (bCopy)
2834 pDocShell->GetUndoManager()->AddUndoAction(
2835 new ScUndoCopyTab(
2836 pDocShell, pSrcTabs.release(), pDestTabs.release(), pDestNames.release()));
2838 else
2840 pDocShell->GetUndoManager()->AddUndoAction(
2841 new ScUndoMoveTab(
2842 pDocShell, pSrcTabs.release(), pDestTabs.release(), pTabNames.release(), pDestNames.release()));
2846 SCTAB nNewTab = nDestTab;
2847 if (nNewTab == SC_TAB_APPEND)
2848 nNewTab = pDoc->GetTableCount()-1;
2849 else if (!bCopy && nTab<nDestTab)
2850 nNewTab--;
2852 SetTabNo( nNewTab, true );
2854 //#i29848# adjust references to data on the copied sheet
2855 if( bCopy )
2856 ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab );
2860 void ScViewFunc::ShowTable( const std::vector<OUString>& rNames )
2862 ScDocShell* pDocSh = GetViewData().GetDocShell();
2863 ScDocument& rDoc = pDocSh->GetDocument();
2864 bool bUndo(rDoc.IsUndoEnabled());
2866 std::vector<SCTAB> undoTabs;
2867 OUString aName;
2868 SCTAB nPos = 0;
2870 bool bFound(false);
2872 for (std::vector<OUString>::const_iterator itr=rNames.begin(), itrEnd = rNames.end(); itr!=itrEnd; ++itr)
2874 aName = *itr;
2875 if (rDoc.GetTable(aName, nPos))
2877 rDoc.SetVisible( nPos, true );
2878 SetTabNo( nPos, true );
2879 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2880 if (!bFound)
2881 bFound = true;
2882 if (bUndo)
2883 undoTabs.push_back(nPos);
2886 if (bFound)
2888 if (bUndo)
2890 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, undoTabs, true ) );
2892 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2893 pDocSh->SetDocumentModified();
2897 void ScViewFunc::HideTable( const ScMarkData& rMark )
2899 ScDocShell* pDocSh = GetViewData().GetDocShell();
2900 ScDocument& rDoc = pDocSh->GetDocument();
2901 bool bUndo(rDoc.IsUndoEnabled());
2902 SCTAB nVisible = 0;
2903 SCTAB nTabCount = rDoc.GetTableCount();
2905 SCTAB nTabSelCount = rMark.GetSelectCount();
2907 // check to make sure we won't hide all sheets. we need at least one visible at all times.
2908 for ( SCTAB i=0; i < nTabCount && nVisible <= nTabSelCount ; i++ )
2909 if (rDoc.IsVisible(i))
2910 ++nVisible;
2912 if (nVisible > nTabSelCount)
2914 SCTAB nTab;
2915 ScMarkData::MarkedTabsType::const_iterator it;
2916 std::vector<SCTAB> undoTabs;
2918 ScMarkData::MarkedTabsType selectedTabs = rMark.GetSelectedTabs();
2919 for (it=selectedTabs.begin(); it!=selectedTabs.end(); ++it)
2921 nTab = *it;
2922 if (rDoc.IsVisible( nTab ))
2924 rDoc.SetVisible( nTab, false );
2925 // Update views
2926 pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2927 SetTabNo( nTab, true );
2928 // Store for undo
2929 if (bUndo)
2930 undoTabs.push_back(nTab);
2933 if (bUndo)
2935 pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, undoTabs, false ) );
2938 // Update views
2939 SfxGetpApp()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2940 pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2941 pDocSh->SetDocumentModified();
2945 void ScViewFunc::InsertSpecialChar( const OUString& rStr, const vcl::Font& rFont )
2947 ScEditableTester aTester( this );
2948 if (!aTester.IsEditable())
2950 ErrorMessage(aTester.GetMessageId());
2951 return;
2954 const sal_Unicode* pChar = rStr.getStr();
2955 ScTabViewShell* pViewShell = GetViewData().GetViewShell();
2956 SvxFontItem aFontItem( rFont.GetFamily(),
2957 rFont.GetName(),
2958 rFont.GetStyleName(),
2959 rFont.GetPitch(),
2960 rFont.GetCharSet(),
2961 ATTR_FONT );
2963 // if string contains WEAK characters, set all fonts
2964 SvtScriptType nScript;
2965 ScDocument* pDoc = GetViewData().GetDocument();
2966 if ( pDoc->HasStringWeakCharacters( rStr ) )
2967 nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
2968 else
2969 nScript = pDoc->GetStringScriptType( rStr );
2971 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() );
2972 aSetItem.PutItemForScriptType( nScript, aFontItem );
2973 ApplyUserItemSet( aSetItem.GetItemSet() );
2975 while ( *pChar )
2976 pViewShell->TabKeyInput( KeyEvent( *(pChar++), vcl::KeyCode() ) );
2979 void ScViewFunc::UpdateLineAttrs( SvxBorderLine& rLine,
2980 const SvxBorderLine* pDestLine,
2981 const SvxBorderLine* pSrcLine,
2982 bool bColor )
2984 if ( pSrcLine && pDestLine )
2986 if ( bColor )
2988 rLine.SetColor ( pSrcLine->GetColor() );
2989 rLine.SetBorderLineStyle(pDestLine->GetBorderLineStyle());
2990 rLine.SetWidth ( pDestLine->GetWidth() );
2992 else
2994 rLine.SetColor ( pDestLine->GetColor() );
2995 rLine.SetBorderLineStyle(pSrcLine->GetBorderLineStyle());
2996 rLine.SetWidth ( pSrcLine->GetWidth() );
3001 #define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \
3002 pBoxLine = aBoxItem.Get##LINE(); \
3003 if ( pBoxLine ) \
3005 if ( pLine ) \
3007 UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly ); \
3008 aBoxItem.SetLine( &aLine, BOXLINE ); \
3010 else \
3011 aBoxItem.SetLine( NULL, BOXLINE ); \
3014 void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine,
3015 bool bColorOnly )
3017 // Not editable only due to a matrix? Attribute is ok anyhow.
3018 bool bOnlyNotBecauseOfMatrix;
3019 if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
3021 ErrorMessage(STR_PROTECTIONERR);
3022 return;
3025 ScDocument* pDoc = GetViewData().GetDocument();
3026 ScMarkData aFuncMark( GetViewData().GetMarkData() ); // local copy for UnmarkFiltered
3027 ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
3028 ScDocShell* pDocSh = GetViewData().GetDocShell();
3029 const ScPatternAttr* pSelAttrs = GetSelectionPattern();
3030 const SfxItemSet& rSelItemSet = pSelAttrs->GetItemSet();
3032 const SfxPoolItem* pBorderAttr = NULL;
3033 SfxItemState eItemState = rSelItemSet.GetItemState( ATTR_BORDER, true, &pBorderAttr );
3035 const SfxPoolItem* pTLBRItem = 0;
3036 SfxItemState eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, true, &pTLBRItem );
3038 const SfxPoolItem* pBLTRItem = 0;
3039 SfxItemState eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, true, &pBLTRItem );
3041 // any of the lines visible?
3042 if( (eItemState != SfxItemState::DEFAULT) || (eTLBRState != SfxItemState::DEFAULT) || (eBLTRState != SfxItemState::DEFAULT) )
3044 // none of the lines don't care?
3045 if( (eItemState != SfxItemState::DONTCARE) && (eTLBRState != SfxItemState::DONTCARE) && (eBLTRState != SfxItemState::DONTCARE) )
3047 boost::scoped_ptr<SfxItemSet> pOldSet(new SfxItemSet(
3048 *(pDoc->GetPool()),
3049 ATTR_PATTERN_START,
3050 ATTR_PATTERN_END ));
3051 boost::scoped_ptr<SfxItemSet> pNewSet(new SfxItemSet(
3052 *(pDoc->GetPool()),
3053 ATTR_PATTERN_START,
3054 ATTR_PATTERN_END ));
3056 const SvxBorderLine* pBoxLine = NULL;
3057 SvxBorderLine aLine;
3059 // here pBoxLine is used
3061 if( pBorderAttr )
3063 SvxBoxItem aBoxItem( *static_cast<const SvxBoxItem*>(pBorderAttr) );
3064 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
3066 SET_LINE_ATTRIBUTES(Top,SvxBoxItemLine::TOP)
3067 SET_LINE_ATTRIBUTES(Bottom,SvxBoxItemLine::BOTTOM)
3068 SET_LINE_ATTRIBUTES(Left,SvxBoxItemLine::LEFT)
3069 SET_LINE_ATTRIBUTES(Right,SvxBoxItemLine::RIGHT)
3071 aBoxInfoItem.SetLine( aBoxItem.GetTop(), SvxBoxInfoItemLine::HORI );
3072 aBoxInfoItem.SetLine( aBoxItem.GetLeft(), SvxBoxInfoItemLine::VERT );
3073 aBoxInfoItem.ResetFlags(); // set Lines to Valid
3075 pOldSet->Put( *pBorderAttr );
3076 pNewSet->Put( aBoxItem );
3077 pNewSet->Put( aBoxInfoItem );
3080 if( pTLBRItem && static_cast<const SvxLineItem*>(pTLBRItem)->GetLine() )
3082 SvxLineItem aTLBRItem( *static_cast<const SvxLineItem*>(pTLBRItem) );
3083 UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly );
3084 aTLBRItem.SetLine( &aLine );
3085 pOldSet->Put( *pTLBRItem );
3086 pNewSet->Put( aTLBRItem );
3089 if( pBLTRItem && static_cast<const SvxLineItem*>(pBLTRItem)->GetLine() )
3091 SvxLineItem aBLTRItem( *static_cast<const SvxLineItem*>(pBLTRItem) );
3092 UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly );
3093 aBLTRItem.SetLine( &aLine );
3094 pOldSet->Put( *pBLTRItem );
3095 pNewSet->Put( aBLTRItem );
3098 ApplyAttributes( pNewSet.get(), pOldSet.get() );
3100 else // if ( eItemState == SfxItemState::DONTCARE )
3102 aFuncMark.MarkToMulti();
3103 pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly );
3106 ScRange aMarkRange;
3107 aFuncMark.GetMultiMarkArea( aMarkRange );
3108 SCCOL nStartCol = aMarkRange.aStart.Col();
3109 SCROW nStartRow = aMarkRange.aStart.Row();
3110 SCTAB nStartTab = aMarkRange.aStart.Tab();
3111 SCCOL nEndCol = aMarkRange.aEnd.Col();
3112 SCROW nEndRow = aMarkRange.aEnd.Row();
3113 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3114 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
3115 nEndCol, nEndRow, nEndTab,
3116 PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3118 pDocSh->UpdateOle( &GetViewData() );
3119 pDocSh->SetDocumentModified();
3123 #undef SET_LINE_ATTRIBUTES
3125 void ScViewFunc::SetValidation( const ScValidationData& rNew )
3127 ScDocument* pDoc = GetViewData().GetDocument();
3128 sal_uLong nIndex = pDoc->AddValidationEntry(rNew); // for it there is no Undo
3129 SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex );
3131 ApplyAttr( aItem ); // with Paint and Undo...
3134 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */