Update to m13
[ooovba.git] / applied_patches / 0499-calc-find-replace-empty-cells-sc.diff
blob4d20135c6955c5c0895f5da0b20ec6b5ec0039ce
1 --- sc/inc/table.hxx.old 2009-04-06 16:41:59.000000000 +0000
2 +++ sc/inc/table.hxx 2009-04-06 16:42:06.000000000 +0000
3 @@ -272,6 +272,7 @@ public:
4 { return aCol[rPos.Col()].GetCell( rPos.Row() ); }
5 ScBaseCell* GetCell( SCCOL nCol, SCROW nRow ) const;
7 + void GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const;
8 void GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
10 /** Returns the pointer to a cell note object at the passed cell address. */
11 @@ -669,6 +670,16 @@ private:
12 BOOL SearchAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark);
13 BOOL ReplaceAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
14 ScDocument* pUndoDoc);
15 + bool SearchAndReplaceEmptyCells(
16 + const SvxSearchItem& rSearchItem,
17 + SCCOL& rCol, SCROW& rRow, ScMarkData& rMark,
18 + String& rUndoStr, ScDocument* pUndoDoc);
19 + bool SearchRangeForEmptyCell(const ScRange& rRange,
20 + const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow,
21 + String& rUndoStr, ScDocument* pUndoDoc);
22 + bool SearchRangeForAllEmptyCells(const ScRange& rRange,
23 + const SvxSearchItem& rSearchItem, ScMarkData& rMark,
24 + String& rUndoStr, ScDocument* pUndoDoc);
26 // benutzen globalen SortParam:
27 BOOL IsSorted(SCCOLROW nStart, SCCOLROW nEnd);
28 --- sc/source/core/data/column.cxx.old 2009-04-06 16:41:50.000000000 +0000
29 +++ sc/source/core/data/column.cxx 2009-04-06 16:42:06.000000000 +0000
30 @@ -1370,7 +1370,24 @@ void ScColumn::CopyToColumn(SCROW nRow1,
31 CloneCell( i, nFlags, *rColumn.pDocument, aDestPos );
33 if (pNew)
34 - rColumn.Insert(pItems[i].nRow, pNew);
35 + {
36 + // Special case to allow removing of cell instances. A
37 + // string cell with empty content is used to indicate an
38 + // empty cell.
39 + if (pNew->GetCellType() == CELLTYPE_STRING)
40 + {
41 + String aStr;
42 + static_cast<ScStringCell*>(pNew)->GetString(aStr);
43 + if (aStr.Len() == 0)
44 + // A string cell with empty string. Delete the cell itself.
45 + rColumn.Delete(pItems[i].nRow);
46 + else
47 + // non-empty string cell
48 + rColumn.Insert(pItems[i].nRow, pNew);
49 + }
50 + else
51 + rColumn.Insert(pItems[i].nRow, pNew);
52 + }
56 --- sc/source/core/data/table2.cxx.old 2009-04-06 16:41:51.000000000 +0000
57 +++ sc/source/core/data/table2.cxx 2009-04-06 16:42:06.000000000 +0000
58 @@ -938,6 +938,11 @@ ScBaseCell* ScTable::GetCell( SCCOL nCol
59 return NULL;
62 +void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
64 + rCol = 0;
65 + rRow = 0;
68 void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
70 --- sc/source/core/data/table6.cxx.old 2009-04-02 10:45:01.000000000 +0000
71 +++ sc/source/core/data/table6.cxx 2009-04-06 16:42:06.000000000 +0000
72 @@ -52,6 +52,8 @@
73 //--------------------------------------------------------------------------
76 +using ::com::sun::star::util::SearchOptions;
78 BOOL lcl_GetTextWithBreaks( const ScEditCell& rCell, ScDocument* pDoc, String& rVal )
80 // TRUE = more than 1 paragraph
81 @@ -660,6 +662,12 @@ BOOL ScTable::SearchAndReplace(const Svx
82 com::sun::star::util::SearchOptions aSearchOptions = rSearchItem.GetSearchOptions();
83 aSearchOptions.Locale = *ScGlobal::pLocale;
85 + if (!aSearchOptions.searchString.getLength())
86 + {
87 + // Search for empty cells.
88 + return SearchAndReplaceEmptyCells(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
89 + }
91 // #107259# reflect UseAsianOptions flag in SearchOptions
92 // (use only ignore case and width if asian options are disabled).
93 // This is also done in SvxSearchDialog CommandHdl, but not in API object.
94 @@ -686,6 +694,274 @@ BOOL ScTable::SearchAndReplace(const Svx
95 return bFound;
98 +bool ScTable::SearchAndReplaceEmptyCells(
99 + const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, ScMarkData& rMark,
100 + String& rUndoStr, ScDocument* pUndoDoc)
102 + SCCOL nColStart, nColEnd;
103 + SCROW nRowStart, nRowEnd;
104 + GetFirstDataPos(nColStart, nRowStart);
105 + GetLastDataPos(nColEnd, nRowEnd);
107 + ScRangeList aRanges;
108 + aRanges.Append(ScRange(nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab));
110 + if (rSearchItem.GetSelection())
112 + // current selection only.
113 + if (!rMark.IsMarked() && !rMark.IsMultiMarked())
114 + // There is no selection. Bail out.
115 + return false;
117 + ScRangeList aMarkedRanges, aNewRanges;
118 + rMark.FillRangeListWithMarks(&aMarkedRanges, true);
119 + for (ScRangePtr p = aMarkedRanges.First(); p; p = aMarkedRanges.Next())
121 + if (p->aStart.Col() > nColEnd || p->aStart.Row() > nRowEnd)
122 + // This range is outside the data area. Skip it.
123 + continue;
125 + // Shrink the range into data area only.
126 + if (p->aStart.Col() < nColStart)
127 + p->aStart.SetCol(rCol);
128 + if (p->aStart.Row() < nRowStart)
129 + p->aStart.SetRow(rRow);
131 + if (p->aEnd.Col() > nColEnd)
132 + p->aEnd.SetCol(nColEnd);
133 + if (p->aEnd.Row() > nRowEnd)
134 + p->aEnd.SetRow(nRowEnd);
136 + aNewRanges.Append(*p);
138 + aRanges = aNewRanges;
141 + sal_uInt16 nCommand = rSearchItem.GetCommand();
142 + if (nCommand == SVX_SEARCHCMD_FIND || nCommand == SVX_SEARCHCMD_REPLACE)
144 + if (rSearchItem.GetBackward())
146 + for (ScRangePtr p = aRanges.Last(); p; p = aRanges.Prev())
148 + if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr, pUndoDoc))
149 + return true;
152 + else
154 + for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
156 + if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr, pUndoDoc))
157 + return true;
161 + else if (nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL)
163 + bool bFound = false;
164 + ScMarkData aNewMark(rMark);
165 + aNewMark.ResetMark();
166 + for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
167 + bFound |= SearchRangeForAllEmptyCells(*p, rSearchItem, aNewMark, rUndoStr, pUndoDoc);
168 + rMark = aNewMark;
169 + return bFound;
171 + return false;
174 +bool ScTable::SearchRangeForEmptyCell(
175 + const ScRange& rRange, const SvxSearchItem& rSearchItem,
176 + SCCOL& rCol, SCROW& rRow, String& rUndoStr, ScDocument* /*pUndoDoc*/)
178 + sal_uInt16 nCmd = rSearchItem.GetCommand();
179 + if (rSearchItem.GetBackward())
181 + // backward search
182 + if (rSearchItem.GetRowDirection())
184 + // row direction.
185 + SCROW nBeginRow = rRange.aEnd.Row() > rRow ? rRow : rRange.aEnd.Row();
186 + for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
188 + SCCOL nBeginCol = rRange.aEnd.Col();
189 + if (nRow == rRow && nBeginCol >= rCol)
190 + // always start from one cell before the cursor.
191 + nBeginCol = rCol - (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
193 + for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
195 + ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
196 + if (!pCell)
198 + // empty cell found.
199 + rCol = nCol;
200 + rRow = nRow;
201 + if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
202 + rSearchItem.GetReplaceString().Len())
204 + aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
205 + rUndoStr = String();
207 + return true;
212 + else
214 + // column direction.
215 + SCCOL nBeginCol = rRange.aEnd.Col() > rCol ? rCol : rRange.aEnd.Col();
216 + for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
218 + SCROW nBeginRow = rRange.aEnd.Row();
219 + if (nCol == rCol && nBeginRow >= rRow)
220 + // always start from one cell before the cursor.
221 + nBeginRow = rRow - (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
222 + for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
223 + {
224 + ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
225 + if (!pCell)
227 + // empty cell found.
228 + rCol = nCol;
229 + rRow = nRow;
230 + if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
231 + rSearchItem.GetReplaceString().Len())
233 + aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
234 + rUndoStr = String();
236 + return true;
242 + else
244 + // forward search
245 + if (rSearchItem.GetRowDirection())
247 + // row direction.
248 + SCROW nBeginRow = rRange.aStart.Row() < rRow ? rRow : rRange.aStart.Row();
249 + for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
251 + SCCOL nBeginCol = rRange.aStart.Col();
252 + if (nRow == rRow && nBeginCol <= rCol)
253 + // always start from one cell past the cursor.
254 + nBeginCol = rCol + (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
255 + for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
257 + ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
258 + if (!pCell)
260 + // empty cell found.
261 + rCol = nCol;
262 + rRow = nRow;
263 + if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
264 + rSearchItem.GetReplaceString().Len())
266 + aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
267 + rUndoStr = String();
269 + return true;
274 + else
276 + // column direction.
277 + SCCOL nBeginCol = rRange.aStart.Col() < rCol ? rCol : rRange.aStart.Col();
278 + for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
280 + SCROW nBeginRow = rRange.aStart.Row();
281 + if (nCol == rCol && nBeginRow <= rRow)
282 + // always start from one cell past the cursor.
283 + nBeginRow = rRow + (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
284 + for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
285 + {
286 + ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
287 + if (!pCell)
289 + // empty cell found.
290 + rCol = nCol;
291 + rRow = nRow;
292 + if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
293 + rSearchItem.GetReplaceString().Len())
295 + aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
296 + rUndoStr = String();
298 + return true;
304 + return false;
307 +bool ScTable::SearchRangeForAllEmptyCells(
308 + const ScRange& rRange, const SvxSearchItem& rSearchItem, ScMarkData& rMark,
309 + String& rUndoStr, ScDocument* pUndoDoc)
311 + bool bFound = false;
312 + bool bReplace = (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) &&
313 + (rSearchItem.GetReplaceString().Len() > 0);
315 + for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
317 + if (aCol[nCol].IsEmptyData())
319 + // The entire column is empty. Add the whole column and move on.
320 + rMark.SetMultiMarkArea(
321 + ScRange(nCol, rRange.aStart.Row(), nTab, nCol, rRange.aEnd.Row(), nTab));
322 + bFound = true;
324 + if (bReplace)
326 + const String& rNewStr = rSearchItem.GetReplaceString();
327 + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
328 + {
329 + aCol[nCol].Insert(nRow, new ScStringCell(rNewStr));
330 + if (pUndoDoc)
331 + // TODO: I'm using a string cell with empty content to
332 + // trigger deletion of cell instance on undo. Maybe I
333 + // should create a new cell type for this?
334 + pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
336 + rUndoStr = String();
338 + continue;
341 + for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
343 + ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
344 + if (!pCell)
345 + {
346 + // empty cell found
347 + rMark.SetMultiMarkArea(ScRange(nCol, nRow, nTab));
348 + bFound = true;
350 + if (bReplace)
351 + {
352 + aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
353 + if (pUndoDoc)
354 + // TODO: I'm using a string cell with empty content to
355 + // trigger deletion of cell instance on undo. Maybe I
356 + // should create a new cell type for this?
357 + pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
362 + return bFound;
369 --- sc/source/ui/view/tabvwsha.cxx.old 2009-04-06 16:41:51.000000000 +0000
370 +++ sc/source/ui/view/tabvwsha.cxx 2009-04-06 16:42:06.000000000 +0000
371 @@ -223,9 +223,14 @@ void __EXPORT ScTabViewShell::GetState(
372 GetViewData()->GetDocShell()->GetStatePageStyle( *this, rSet, nTab );
373 break;
375 - case SID_SEARCH_ITEM:
376 - rSet.Put( ScGlobal::GetSearchItem() );
377 - break;
378 + case SID_SEARCH_ITEM:
380 + SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy.
381 + // Search on current selection if a range is marked.
382 + aItem.SetSelection(rMark.IsMarked());
383 + rSet.Put(aItem);
384 + break;
387 case SID_SEARCH_OPTIONS: