LibreOffice Module sc (master) 1
XMLChangeTrackingImportHelper.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
21#include <formulacell.hxx>
22#include <document.hxx>
23#include <rangeutl.hxx>
24#include <tools/datetime.hxx>
25#include <osl/diagnose.h>
26#include <svl/numformat.hxx>
27#include <svl/zforlist.hxx>
29#include <utility>
30
31constexpr OStringLiteral SC_CHANGE_ID_PREFIX = "ct";
32
34 ScCellValue aCell, OUString aFormulaAddress, OUString aFormula,
35 const formula::FormulaGrammar::Grammar eTempGrammar, OUString aInputString,
36 const double& rValue, const sal_uInt16 nTempType, const ScMatrixMode nTempMatrixFlag, const sal_Int32 nTempMatrixCols,
37 const sal_Int32 nTempMatrixRows ) :
38 maCell(std::move(aCell)),
39 sFormulaAddress(std::move(aFormulaAddress)),
40 sFormula(std::move(aFormula)),
41 sInputString(std::move(aInputString)),
42 fValue(rValue),
43 nMatrixCols(nTempMatrixCols),
44 nMatrixRows(nTempMatrixRows),
45 eGrammar( eTempGrammar),
46 nType(nTempType),
47 nMatrixFlag(nTempMatrixFlag)
48{
49}
50
52
54{
55 if (!maCell.isEmpty())
56 return maCell;
57
58 if (!sFormula.isEmpty() && !sFormulaAddress.isEmpty())
59 {
60 ScAddress aPos;
61 sal_Int32 nOffset(0);
64 maCell.getFormula()->SetMatColsRows(static_cast<SCCOL>(nMatrixCols), static_cast<SCROW>(nMatrixRows));
65 }
66
67 if ((nType == css::util::NumberFormat::DATE || nType == css::util::NumberFormat::TIME) && sInputString.isEmpty())
68 {
69 sal_uInt32 nFormat(0);
71 nFormat = rDoc.GetFormatTable()->GetStandardFormat( SvNumFormatType::DATE, ScGlobal::eLnge );
72 else if (nType == css::util::NumberFormat::TIME)
73 nFormat = rDoc.GetFormatTable()->GetStandardFormat( SvNumFormatType::TIME, ScGlobal::eLnge );
75 }
76
77 return maCell;
78}
79
81 : nActionNumber(0),
82 nRejectingNumber(0),
83 nPreviousAction(0),
84 nActionType(nTempActionType),
85 nActionState(SC_CAS_VIRGIN)
86{
87}
88
90{
91}
92
94 : ScMyBaseAction(nActionTypeP)
95{
96}
97
99{
100}
101
103 : ScMyBaseAction(nActionTypeP),
104 nD(0)
105{
106}
107
109{
110}
111
114{
115}
116
118{
119}
120
123{
124}
125
127{
128}
129
132{
133}
134
136{
137}
138
140 pTrack(nullptr),
141 nMultiSpanned(0),
142 nMultiSpannedSlaveCount(0)
143{
144}
145
147{
148}
149
151{
152 OSL_ENSURE(!pCurrentAction, "a not inserted action");
153 switch (nActionType)
154 {
158 {
159 pCurrentAction = std::make_unique<ScMyInsAction>(nActionType);
160 }
161 break;
165 {
166 pCurrentAction = std::make_unique<ScMyDelAction>(nActionType);
167 }
168 break;
169 case SC_CAT_MOVE:
170 {
171 pCurrentAction = std::make_unique<ScMyMoveAction>();
172 }
173 break;
174 case SC_CAT_CONTENT:
175 {
176 pCurrentAction = std::make_unique<ScMyContentAction>();
177 }
178 break;
179 case SC_CAT_REJECT:
180 {
181 pCurrentAction = std::make_unique<ScMyRejAction>();
182 }
183 break;
184 default:
185 {
186 // added to avoid warnings
187 }
188 }
189}
190
192{
193 sal_uInt32 nResult(0);
194 if (!sID.empty())
195 {
196 if (sID.substr(0, SC_CHANGE_ID_PREFIX.getLength()) == SC_CHANGE_ID_PREFIX)
197 {
198 sal_Int32 nValue;
200 OSL_ENSURE(nValue > 0, "wrong change action ID");
201 nResult = nValue;
202 }
203 else
204 {
205 OSL_FAIL("wrong change action ID");
206 }
207 }
208 return nResult;
209}
210
212{
213 pCurrentAction->aInfo = aInfo;
214 aUsers.insert(aInfo.sUser);
215}
216
217void ScXMLChangeTrackingImportHelper::SetPreviousChange(const sal_uInt32 nPreviousAction,
218 ScMyCellInfo* pCellInfo)
219{
220 OSL_ENSURE(pCurrentAction->nActionType == SC_CAT_CONTENT, "wrong action type");
221 ScMyContentAction* pAction = static_cast<ScMyContentAction*>(pCurrentAction.get());
222 pAction->nPreviousAction = nPreviousAction;
223 pAction->pCellInfo.reset( pCellInfo );
224}
225
226void ScXMLChangeTrackingImportHelper::SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
227{
228 OSL_ENSURE(((pCurrentAction->nActionType != SC_CAT_MOVE) &&
229 (pCurrentAction->nActionType != SC_CAT_CONTENT) &&
230 (pCurrentAction->nActionType != SC_CAT_REJECT)), "wrong action type");
231 OSL_ENSURE(nCount > 0, "wrong count");
232 switch(pCurrentAction->nActionType)
233 {
236 {
237 pCurrentAction->aBigRange.Set(nPosition, ScBigRange::nRangeMin, nTable,
238 nPosition + nCount - 1, ScBigRange::nRangeMax, nTable);
239 }
240 break;
243 {
244 pCurrentAction->aBigRange.Set(ScBigRange::nRangeMin, nPosition, nTable,
245 ScBigRange::nRangeMax, nPosition + nCount - 1, nTable);
246 }
247 break;
250 {
253 }
254 break;
255 default:
256 {
257 // added to avoid warnings
258 }
259 }
260}
261
263{
264 pCurrentAction->aDeletedList.emplace_back( nID, nullptr );
265}
266
267void ScXMLChangeTrackingImportHelper::AddDeleted(const sal_uInt32 nID, std::unique_ptr<ScMyCellInfo> pCellInfo)
268{
269 pCurrentAction->aDeletedList.emplace_back( nID, std::move(pCellInfo) );
270}
271
272void ScXMLChangeTrackingImportHelper::SetMultiSpanned(const sal_Int16 nTempMultiSpanned)
273{
274 if (nTempMultiSpanned)
275 {
276 OSL_ENSURE(((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
277 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS)), "wrong action type");
278 nMultiSpanned = nTempMultiSpanned;
280 }
281}
282
283void ScXMLChangeTrackingImportHelper::SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
284{
285 if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
286 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
287 {
288 static_cast<ScMyDelAction*>(pCurrentAction.get())->moInsCutOff.emplace( nID, nPosition );
289 }
290 else
291 {
292 OSL_FAIL("wrong action type");
293 }
294}
295
296void ScXMLChangeTrackingImportHelper::AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
297{
298 if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
299 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
300 {
301 static_cast<ScMyDelAction*>(pCurrentAction.get())->aMoveCutOffs.push_back(ScMyMoveCutOff(nID, nStartPosition, nEndPosition));
302 }
303 else
304 {
305 OSL_FAIL("wrong action type");
306 }
307}
308
309void ScXMLChangeTrackingImportHelper::SetMoveRanges(const ScBigRange& aSourceRange, const ScBigRange& aTargetRange)
310{
311 if (pCurrentAction->nActionType == SC_CAT_MOVE)
312 {
313 static_cast<ScMyMoveAction*>(pCurrentAction.get())->pMoveRanges.reset( new ScMyMoveRanges(aSourceRange, aTargetRange) );
314 }
315 else
316 {
317 OSL_FAIL("wrong action type");
318 }
319}
320
322{
323 if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
324 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
325 {
327 {
328 static_cast<ScMyDelAction*>(pCurrentAction.get())->nD = nMultiSpannedSlaveCount;
329 }
332 {
333 nMultiSpanned = 0;
335 }
336 }
337 else
338 {
339 OSL_FAIL("wrong action type");
340 }
341}
342
343void ScXMLChangeTrackingImportHelper::AddGenerated(std::unique_ptr<ScMyCellInfo> pCellInfo, const ScBigRange& aBigRange)
344{
345 ScMyGenerated aGenerated { aBigRange, 0, std::move(pCellInfo) };
346 if (pCurrentAction->nActionType == SC_CAT_MOVE)
347 {
348 static_cast<ScMyMoveAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
349 }
350 else if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
351 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
352 {
353 static_cast<ScMyDelAction*>(pCurrentAction.get())->aGeneratedList.push_back(std::move(aGenerated));
354 }
355 else
356 {
357 OSL_FAIL("try to insert a generated action to a wrong action");
358 }
359}
360
362{
363 if (!pCurrentAction)
364 {
365 OSL_FAIL("no current action");
366 return;
367 }
368
369 if ((pCurrentAction->nActionType == SC_CAT_DELETE_COLS) ||
370 (pCurrentAction->nActionType == SC_CAT_DELETE_ROWS))
372
373 if (pCurrentAction->nActionNumber > 0)
374 aActions.push_back(std::move(pCurrentAction));
375 else
376 {
377 OSL_FAIL("no current action");
378 }
379
380 pCurrentAction = nullptr;
381}
382
383void ScXMLChangeTrackingImportHelper::ConvertInfo(const ScMyActionInfo& aInfo, OUString& rUser, DateTime& aDateTime)
384{
385 aDateTime = DateTime( aInfo.aDateTime);
386
387 // old files didn't store nanoseconds, enable again
388 if ( aInfo.aDateTime.NanoSeconds )
389 pTrack->SetTimeNanoSeconds( true );
390
391 const std::set<OUString>& rUsers = pTrack->GetUserCollection();
392 std::set<OUString>::const_iterator it = rUsers.find(aInfo.sUser);
393 if (it != rUsers.end())
394 {
395 // It's probably pointless to do this.
396 rUser = *it;
397 }
398 else
399 rUser = aInfo.sUser; // shouldn't happen
400}
401
402std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateInsertAction(const ScMyInsAction* pAction)
403{
404 DateTime aDateTime( Date(0), tools::Time(0) );
405 OUString aUser;
406 ConvertInfo(pAction->aInfo, aUser, aDateTime);
407
408 OUString sComment (pAction->aInfo.sComment);
409
410 return std::make_unique<ScChangeActionIns>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
411 pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType);
412}
413
414std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateDeleteAction(const ScMyDelAction* pAction)
415{
416 DateTime aDateTime( Date(0), tools::Time(0) );
417 OUString aUser;
418 ConvertInfo(pAction->aInfo, aUser, aDateTime);
419
420 OUString sComment (pAction->aInfo.sComment);
421
422 return std::make_unique<ScChangeActionDel>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
423 pAction->aBigRange, aUser, aDateTime, sComment, pAction->nActionType, pAction->nD, pTrack);
424}
425
426std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateMoveAction(const ScMyMoveAction* pAction)
427{
428 OSL_ENSURE(pAction->pMoveRanges, "no move ranges");
429 if (pAction->pMoveRanges)
430 {
431 DateTime aDateTime( Date(0), tools::Time(0) );
432 OUString aUser;
433 ConvertInfo(pAction->aInfo, aUser, aDateTime);
434
435 OUString sComment (pAction->aInfo.sComment);
436
437 return std::make_unique<ScChangeActionMove>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
438 pAction->pMoveRanges->aTargetRange, aUser, aDateTime, sComment, pAction->pMoveRanges->aSourceRange , pTrack);
439 }
440 return nullptr;
441}
442
443std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateRejectionAction(const ScMyRejAction* pAction)
444{
445 DateTime aDateTime( Date(0), tools::Time(0) );
446 OUString aUser;
447 ConvertInfo(pAction->aInfo, aUser, aDateTime);
448
449 OUString sComment (pAction->aInfo.sComment);
450
451 return std::make_unique<ScChangeActionReject>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
452 pAction->aBigRange, aUser, aDateTime, sComment);
453}
454
455std::unique_ptr<ScChangeAction> ScXMLChangeTrackingImportHelper::CreateContentAction(const ScMyContentAction* pAction, ScDocument& rDoc)
456{
457 ScCellValue aCell;
458 OUString sInputString;
459 if (pAction->pCellInfo)
460 {
461 aCell = pAction->pCellInfo->CreateCell(rDoc);
462 sInputString = pAction->pCellInfo->sInputString;
463 }
464
465 DateTime aDateTime( Date(0), tools::Time(0) );
466 OUString aUser;
467 ConvertInfo(pAction->aInfo, aUser, aDateTime);
468
469 OUString sComment (pAction->aInfo.sComment);
470
471 return std::make_unique<ScChangeActionContent>(pAction->nActionNumber, pAction->nActionState, pAction->nRejectingNumber,
472 pAction->aBigRange, aUser, aDateTime, sComment, aCell, &rDoc, sInputString);
473}
474
475void ScXMLChangeTrackingImportHelper::CreateGeneratedActions(std::vector<ScMyGenerated>& rList, ScDocument& rDoc)
476{
477 for (ScMyGenerated & rGenerated : rList)
478 {
479 if (rGenerated.nID != 0)
480 continue;
481 if (!rGenerated.pCellInfo)
482 continue;
483 ScCellValue aCell = rGenerated.pCellInfo->CreateCell(rDoc);
484 if (aCell.isEmpty())
485 continue;
486 rGenerated.nID = pTrack->AddLoadedGenerated(aCell, rGenerated.aBigRange, rGenerated.pCellInfo->sInputString);
487 OSL_ENSURE(rGenerated.nID, "could not insert generated action");
488 }
489}
490
492{
493 if (!pAction->aGeneratedList.empty())
494 {
495 OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
496 (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
497 (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
498 if (pDelAct)
499 {
500 for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
501 {
502 OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
503 pDelAct->SetDeletedInThis(rGenerated.nID, pTrack);
504 }
505 pAction->aGeneratedList.clear();
506 }
507 }
508 if (pAction->moInsCutOff)
509 {
510 OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
511 (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
512 (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
513 ScChangeAction* pChangeAction = pTrack->GetAction(pAction->moInsCutOff->nID);
514 if (pChangeAction && pChangeAction->IsInsertType())
515 {
516 ScChangeActionIns* pInsAction = static_cast<ScChangeActionIns*>(pChangeAction);
517 if (pDelAct)
518 pDelAct->SetCutOffInsert(pInsAction, static_cast<sal_Int16>(pAction->moInsCutOff->nPosition));
519 }
520 else
521 {
522 OSL_FAIL("no cut off insert action");
523 }
524 }
525 if (pAction->aMoveCutOffs.empty())
526 return;
527
528 OSL_ENSURE(((pAction->nActionType == SC_CAT_DELETE_COLS) ||
529 (pAction->nActionType == SC_CAT_DELETE_ROWS) ||
530 (pAction->nActionType == SC_CAT_DELETE_TABS)), "wrong action type");
531 for (auto it = pAction->aMoveCutOffs.crbegin(); it != pAction->aMoveCutOffs.crend(); ++it)
532 {
533 const ScMyMoveCutOff & rCutOff = *it;
534 ScChangeAction* pChangeAction = pTrack->GetAction(rCutOff.nID);
535 if (pChangeAction && (pChangeAction->GetType() == SC_CAT_MOVE))
536 {
537 ScChangeActionMove* pMoveAction = static_cast<ScChangeActionMove*>(pChangeAction);
538 if (pDelAct)
539 pDelAct->AddCutOffMove(pMoveAction, static_cast<sal_Int16>(rCutOff.nStartPosition),
540 static_cast<sal_Int16>(rCutOff.nEndPosition));
541 }
542 else
543 {
544 OSL_FAIL("no cut off move action");
545 }
546 }
547 pAction->aMoveCutOffs.clear();
548}
549
551{
552 if (pAction->aGeneratedList.empty())
553 return;
554
555 if (pAction->nActionType == SC_CAT_MOVE)
556 {
557 if (pMoveAct)
558 {
559 for (const ScMyGenerated & rGenerated : pAction->aGeneratedList)
560 {
561 OSL_ENSURE(rGenerated.nID, "a not inserted generated action");
562 pMoveAct->SetDeletedInThis(rGenerated.nID, pTrack);
563 }
564 pAction->aGeneratedList.clear();
565 }
566 }
567}
568
570{
571 if (!pActContent || !pAction->nPreviousAction)
572 return;
573
574 OSL_ENSURE(pAction->nActionType == SC_CAT_CONTENT, "wrong action type");
575 ScChangeAction* pPrevAct = pTrack->GetAction(pAction->nPreviousAction);
576 if (!pPrevAct || pPrevAct->GetType() != SC_CAT_CONTENT)
577 return;
578
579 ScChangeActionContent* pPrevActContent = static_cast<ScChangeActionContent*>(pPrevAct);
580
581 pActContent->SetPrevContent(pPrevActContent);
582 pPrevActContent->SetNextContent(pActContent);
583 const ScCellValue& rOldCell = pActContent->GetOldCell();
584 if (rOldCell.isEmpty())
585 return;
586
587 pPrevActContent->SetNewCell(rOldCell, &rDoc, OUString());
588}
589
591{
592 ScChangeAction* pAct = pTrack->GetAction(pAction->nActionNumber);
593 if (pAct)
594 {
595 if (!pAction->aDependencies.empty())
596 {
597 for (auto it = pAction->aDependencies.crbegin(); it != pAction->aDependencies.crend(); ++it)
598 pAct->AddDependent(*it, pTrack);
599 pAction->aDependencies.clear();
600 }
601 if (!pAction->aDeletedList.empty())
602 {
603 for (auto it = pAction->aDeletedList.crbegin(); it != pAction->aDeletedList.crend(); ++it)
604 {
605 const ScMyDeleted & rDeleted = *it;
606 pAct->SetDeletedInThis(rDeleted.nID, pTrack);
607 ScChangeAction* pDeletedAct = pTrack->GetAction(rDeleted.nID);
608 if ((pDeletedAct->GetType() == SC_CAT_CONTENT) && rDeleted.pCellInfo)
609 {
610 ScChangeActionContent* pContentAct = static_cast<ScChangeActionContent*>(pDeletedAct);
611 if (rDeleted.pCellInfo)
612 {
613 const ScCellValue& rCell = rDeleted.pCellInfo->CreateCell(rDoc);
614 if (!rCell.equalsWithoutFormat(pContentAct->GetNewCell()))
615 {
616 // #i40704# Don't overwrite SetNewCell result by calling SetNewValue,
617 // instead pass the input string to SetNewCell.
618 pContentAct->SetNewCell(rCell, &rDoc, rDeleted.pCellInfo->sInputString);
619 }
620 }
621 }
622 }
623 pAction->aDeletedList.clear();
624 }
625 if ((pAction->nActionType == SC_CAT_DELETE_COLS) ||
626 (pAction->nActionType == SC_CAT_DELETE_ROWS))
627 SetDeletionDependencies(static_cast<ScMyDelAction*>(pAction), static_cast<ScChangeActionDel*>(pAct));
628 else if (pAction->nActionType == SC_CAT_MOVE)
629 SetMovementDependencies(static_cast<ScMyMoveAction*>(pAction), static_cast<ScChangeActionMove*>(pAct));
630 else if (pAction->nActionType == SC_CAT_CONTENT)
631 SetContentDependencies(static_cast<ScMyContentAction*>(pAction), static_cast<ScChangeActionContent*>(pAct), rDoc);
632 }
633 else
634 {
635 OSL_FAIL("could not find the action");
636 }
637}
638
640{
641 ScChangeAction* pChangeAction = pTrack->GetAction(pAction->nActionNumber);
642 if (!pChangeAction)
643 return;
644
645 assert(dynamic_cast<ScChangeActionContent*>(pChangeAction));
646 ScChangeActionContent* pChangeActionContent = static_cast<ScChangeActionContent*>(pChangeAction);
647 if (!pChangeActionContent->IsTopContent() || pChangeActionContent->IsDeletedIn())
648 return;
649
650 sal_Int64 nCol, nRow, nTab, nCol2, nRow2, nTab2;
651 pAction->aBigRange.GetVars(nCol, nRow, nTab, nCol2, nRow2, nTab2);
652 if ((nCol >= 0) && (nCol <= rDoc.MaxCol()) &&
653 (nRow >= 0) && (nRow <= rDoc.MaxRow()) &&
654 (nTab >= 0) && (nTab <= MAXTAB))
655 {
656 ScAddress aAddress (static_cast<SCCOL>(nCol),
657 static_cast<SCROW>(nRow),
658 static_cast<SCTAB>(nTab));
659 ScCellValue aCell;
660 aCell.assign(rDoc, aAddress);
661 if (!aCell.isEmpty())
662 {
663 ScCellValue aNewCell;
664 if (aCell.getType() != CELLTYPE_FORMULA)
665 {
666 aNewCell = aCell;
667 pChangeActionContent->SetNewCell(aNewCell, &rDoc, OUString());
668 pChangeActionContent->SetNewValue(aCell, &rDoc);
669 }
670 else
671 {
672 ScMatrixMode nMatrixFlag = aCell.getFormula()->GetMatrixFlag();
673 // With GRAM_ODFF reference detection is faster on compilation.
674 /* FIXME: new cell should be created with a clone
675 * of the token array instead. Any reason why this
676 * wasn't done? */
678
679 // #i87826# [Collaboration] Rejected move destroys formulas
680 // FIXME: adjust ScFormulaCell::GetFormula(), so that the right formula string
681 // is returned and no further string handling is necessary
682 OUString sFormula2;
683 if ( nMatrixFlag != ScMatrixMode::NONE )
684 {
685 sFormula2 = sFormula.copy( 2, sFormula.getLength() - 3 );
686 }
687 else
688 {
689 sFormula2 = sFormula.copy( 1 );
690 }
691
692 aNewCell.set(new ScFormulaCell(rDoc, aAddress, sFormula2,formula::FormulaGrammar::GRAM_ODFF, nMatrixFlag));
693 if (nMatrixFlag == ScMatrixMode::Formula)
694 {
695 SCCOL nCols;
696 SCROW nRows;
697 aCell.getFormula()->GetMatColsRows(nCols, nRows);
698 aNewCell.getFormula()->SetMatColsRows(nCols, nRows);
699 }
700 aNewCell.getFormula()->SetInChangeTrack(true);
701 pChangeActionContent->SetNewCell(aNewCell, &rDoc, OUString());
702 // #i40704# don't overwrite the formula string via SetNewValue()
703 }
704 }
705 }
706 else
707 {
708 OSL_FAIL("wrong cell position");
709 }
710}
711
713{
714 if (!pDoc)
715 return;
716
717 pTrack = new ScChangeTrack(*pDoc, std::set(aUsers));
718 // old files didn't store nanoseconds, disable until encountered
719 pTrack->SetTimeNanoSeconds( false );
720
721 for (const auto & rAction : aActions)
722 {
723 std::unique_ptr<ScChangeAction> pAction;
724
725 switch (rAction->nActionType)
726 {
730 {
731 pAction = CreateInsertAction(static_cast<ScMyInsAction*>(rAction.get()));
732 }
733 break;
737 {
738 ScMyDelAction* pDelAct = static_cast<ScMyDelAction*>(rAction.get());
739 pAction = CreateDeleteAction(pDelAct);
740 CreateGeneratedActions(pDelAct->aGeneratedList, *pDoc);
741 }
742 break;
743 case SC_CAT_MOVE:
744 {
745 ScMyMoveAction* pMovAct = static_cast<ScMyMoveAction*>(rAction.get());
746 pAction = CreateMoveAction(pMovAct);
747 CreateGeneratedActions(pMovAct->aGeneratedList, *pDoc);
748 }
749 break;
750 case SC_CAT_CONTENT:
751 {
752 pAction = CreateContentAction(static_cast<ScMyContentAction*>(rAction.get()), *pDoc);
753 }
754 break;
755 case SC_CAT_REJECT:
756 {
757 pAction = CreateRejectionAction(static_cast<ScMyRejAction*>(rAction.get()));
758 }
759 break;
760 default:
761 {
762 // added to avoid warnings
763 }
764 }
765
766 if (pAction)
767 pTrack->AppendLoaded(std::move(pAction));
768 else
769 {
770 OSL_FAIL("no action");
771 }
772 }
773 if (pTrack->GetLast())
775
776 auto aItr = aActions.begin();
777 while (aItr != aActions.end())
778 {
779 SetDependencies(aItr->get(), *pDoc);
780
781 if ((*aItr)->nActionType == SC_CAT_CONTENT)
782 ++aItr;
783 else
784 aItr = aActions.erase(aItr);
785 }
786
787 for (const auto& rxAction : aActions)
788 {
789 OSL_ENSURE(rxAction->nActionType == SC_CAT_CONTENT, "wrong action type");
790 SetNewCell(static_cast<ScMyContentAction*>(rxAction.get()), *pDoc);
791 }
792 aActions.clear();
793 if (aProtect.hasElements())
795 else if (pDoc->GetChangeTrack() && pDoc->GetChangeTrack()->IsProtected())
797
798 if ( pTrack->GetLast() )
800
801 pDoc->SetChangeTrack(std::unique_ptr<ScChangeTrack>(pTrack));
802}
803
804/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OStringLiteral SC_CHANGE_ID_PREFIX
const SCTAB MAXTAB
Definition: address.hxx:70
ScChangeActionType
Definition: chgtrack.hxx:63
@ SC_CAT_MOVE
Definition: chgtrack.hxx:71
@ SC_CAT_DELETE_TABS
Definition: chgtrack.hxx:70
@ SC_CAT_INSERT_TABS
Definition: chgtrack.hxx:67
@ SC_CAT_DELETE_ROWS
Definition: chgtrack.hxx:69
@ SC_CAT_CONTENT
Definition: chgtrack.hxx:72
@ SC_CAT_REJECT
Definition: chgtrack.hxx:73
@ SC_CAT_DELETE_COLS
Definition: chgtrack.hxx:68
@ SC_CAT_INSERT_ROWS
Definition: chgtrack.hxx:66
@ SC_CAT_INSERT_COLS
Definition: chgtrack.hxx:65
@ SC_CAS_VIRGIN
Definition: chgtrack.hxx:78
static constexpr sal_Int64 nRangeMin
Definition: bigrange.hxx:150
static constexpr sal_Int64 nRangeMax
Definition: bigrange.hxx:151
void GetVars(sal_Int64 &nCol1, sal_Int64 &nRow1, sal_Int64 &nTab1, sal_Int64 &nCol2, sal_Int64 &nRow2, sal_Int64 &nTab2) const
Definition: bigrange.hxx:127
bool IsTopContent() const
Definition: chgtrack.hxx:700
void SetNewValue(const ScCellValue &rCell, ScDocument *pDoc)
Definition: chgtrack.cxx:1333
void SetPrevContent(ScChangeActionContent *p)
Definition: chgtrack.hxx:730
const ScCellValue & GetNewCell() const
Definition: chgtrack.hxx:740
void SetNextContent(ScChangeActionContent *p)
Definition: chgtrack.hxx:728
void SetNewCell(const ScCellValue &rCell, const ScDocument *pDoc, const OUString &rFormatted)
Definition: chgtrack.cxx:1348
const ScCellValue & GetOldCell() const
Definition: chgtrack.hxx:739
ScChangeActionDelMoveEntry * AddCutOffMove(ScChangeActionMove *pMove, short nFrom, short nTo)
Definition: chgtrack.cxx:842
void SetCutOffInsert(ScChangeActionIns *p, short n)
Definition: chgtrack.hxx:488
void SetDeletedInThis(sal_uLong nActionNumber, const ScChangeTrack *pTrack)
Definition: chgtrack.cxx:590
bool IsDeletedIn() const
Definition: chgtrack.cxx:318
sal_uLong GetActionNumber() const
Definition: chgtrack.hxx:317
ScChangeActionType GetType() const
Definition: chgtrack.hxx:315
bool IsInsertType() const
Definition: chgtrack.cxx:113
ScChangeActionLinkEntry * AddDependent(ScChangeAction *p)
Definition: chgtrack.hxx:251
const std::set< OUString > & GetUserCollection() const
Definition: chgtrack.hxx:972
void AppendLoaded(std::unique_ptr< ScChangeAction > pAppend)
Definition: chgtrack.cxx:2321
ScChangeAction * GetLast() const
Definition: chgtrack.hxx:952
void SetLastSavedActionNumber(sal_uLong nNew)
Definition: chgtrack.cxx:2139
SC_DLLPUBLIC ScChangeAction * GetAction(sal_uLong nAction) const
Definition: chgtrack.cxx:2110
bool IsProtected() const
Definition: chgtrack.hxx:1126
void SetProtection(const css::uno::Sequence< sal_Int8 > &rPass)
Definition: chgtrack.hxx:1122
sal_uLong AddLoadedGenerated(const ScCellValue &rNewCell, const ScBigRange &aBigRange, const OUString &sNewValue)
Definition: chgtrack.cxx:4336
void SetTimeNanoSeconds(bool bVal)
Definition: chgtrack.hxx:1131
const css::uno::Sequence< sal_Int8 > & GetProtection() const
Definition: chgtrack.hxx:1124
void SetActionMax(sal_uLong nTempActionMax)
Definition: chgtrack.hxx:1119
SC_DLLPUBLIC void SetChangeTrack(std::unique_ptr< ScChangeTrack > pTrack)
only for import filter, deletes any existing ChangeTrack via EndChangeTracking() and takes ownership ...
Definition: documen2.cxx:294
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:892
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:893
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:467
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2494
void SetInChangeTrack(bool bVal)
void GetMatColsRows(SCCOL &nCols, SCROW &nRows) const
ScMatrixMode GetMatrixFlag() const
void SetMatColsRows(SCCOL nCols, SCROW nRows)
OUString GetFormula(const formula::FormulaGrammar::Grammar=formula::FormulaGrammar::GRAM_DEFAULT, const ScInterpreterContext *pContext=nullptr) const
static SC_DLLPUBLIC LanguageType eLnge
Definition: global.hxx:560
static bool GetAddressFromString(ScAddress &rAddress, std::u16string_view rAddressStr, const ScDocument &rDocument, formula::FormulaGrammar::AddressConvention eConv, sal_Int32 &nOffset, sal_Unicode cSeparator=' ', sal_Unicode cQuote='\'')
String to Range core.
Definition: rangeutl.cxx:461
void SetMovementDependencies(ScMyMoveAction *pAction, ScChangeActionMove *pMoveAct)
std::unique_ptr< ScChangeAction > CreateMoveAction(const ScMyMoveAction *pAction)
void SetMultiSpanned(const sal_Int16 nMultiSpanned)
void SetNewCell(const ScMyContentAction *pAction, ScDocument &rDoc)
std::unique_ptr< ScChangeAction > CreateContentAction(const ScMyContentAction *pAction, ScDocument &rDoc)
static sal_uInt32 GetIDFromString(std::string_view sID)
std::unique_ptr< ScChangeAction > CreateDeleteAction(const ScMyDelAction *pAction)
void StartChangeAction(const ScChangeActionType nActionType)
std::unique_ptr< ScMyBaseAction > pCurrentAction
void SetActionInfo(const ScMyActionInfo &aInfo)
void AddMoveCutOff(const sal_uInt32 nID, const sal_Int32 nStartPosition, const sal_Int32 nEndPosition)
void SetDependencies(ScMyBaseAction *pAction, ScDocument &rDoc)
void SetPreviousChange(const sal_uInt32 nPreviousAction, ScMyCellInfo *pCellInfo)
void CreateGeneratedActions(std::vector< ScMyGenerated > &rList, ScDocument &rDoc)
void SetMoveRanges(const ScBigRange &aSourceRange, const ScBigRange &aTargetRange)
std::vector< std::unique_ptr< ScMyBaseAction > > aActions
std::unique_ptr< ScChangeAction > CreateRejectionAction(const ScMyRejAction *pAction)
void AddGenerated(std::unique_ptr< ScMyCellInfo > pCellInfo, const ScBigRange &aBigRange)
void SetDeletionDependencies(ScMyDelAction *pAction, ScChangeActionDel *pDelAct)
void ConvertInfo(const ScMyActionInfo &aInfo, OUString &rUser, DateTime &aDateTime)
void SetContentDependencies(const ScMyContentAction *pAction, ScChangeActionContent *pActContent, const ScDocument &rDoc)
void SetPosition(const sal_Int32 nPosition, const sal_Int32 nCount, const sal_Int32 nTable)
std::unique_ptr< ScChangeAction > CreateInsertAction(const ScMyInsAction *pAction)
void SetInsertionCutOff(const sal_uInt32 nID, const sal_Int32 nPosition)
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString, bool bFiltering=false, bool bForceSystemLocale=false)
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
int nCount
OString sFormula
sal_Int16 nValue
ScMatrixMode
@ CELLTYPE_FORMULA
Definition: global.hxx:276
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:398
Store arbitrary cell value of any kind.
Definition: cellvalue.hxx:32
void assign(const ScDocument &rDoc, const ScAddress &rPos)
Take cell value from specified position in specified document.
Definition: cellvalue.cxx:359
bool isEmpty() const
Definition: cellvalue.cxx:519
void set(double fValue)
Definition: cellvalue.cxx:329
bool equalsWithoutFormat(const ScCellValue &r) const
Definition: cellvalue.cxx:524
CellType getType() const
Definition: cellvalue.cxx:296
ScFormulaCell * getFormula() const
Definition: cellvalue.hxx:59
css::util::DateTime aDateTime
std::vector< sal_uInt32 > aDependencies
std::vector< ScMyDeleted > aDeletedList
ScMyBaseAction(const ScChangeActionType nActionType)
ScChangeActionState nActionState
formula::FormulaGrammar::Grammar eGrammar
const ScCellValue & CreateCell(ScDocument &rDoc)
ScMyCellInfo(ScCellValue aCell, OUString sFormulaAddress, OUString sFormula, const formula::FormulaGrammar::Grammar eGrammar, OUString sInputString, const double &fValue, const sal_uInt16 nType, const ScMatrixMode nMatrixFlag, const sal_Int32 nMatrixCols, const sal_Int32 nMatrixRows)
std::unique_ptr< ScMyCellInfo > pCellInfo
virtual ~ScMyDelAction() override
std::optional< ScMyInsertionCutOff > moInsCutOff
std::vector< ScMyMoveCutOff > aMoveCutOffs
ScMyDelAction(const ScChangeActionType nActionType)
std::vector< ScMyGenerated > aGeneratedList
std::unique_ptr< ScMyCellInfo > pCellInfo
ScMyInsAction(const ScChangeActionType nActionType)
virtual ~ScMyInsAction() override
std::vector< ScMyGenerated > aGeneratedList
std::unique_ptr< ScMyMoveRanges > pMoveRanges
virtual ~ScMyMoveAction() override
virtual ~ScMyRejAction() override
sal_Int16 SCTAB
Definition: types.hxx:22
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17