View | Details | Raw Unified | Return to issue 49380
Collapse All | Expand All

(-)sc/inc/table.hxx (+11 lines)
Lines 274-279 public: Link Here
274
					{ return aCol[rPos.Col()].GetCell( rPos.Row() ); }
274
					{ return aCol[rPos.Col()].GetCell( rPos.Row() ); }
275
	ScBaseCell*	GetCell( SCCOL nCol, SCROW nRow ) const;
275
	ScBaseCell*	GetCell( SCCOL nCol, SCROW nRow ) const;
276
276
277
    void        GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const;
277
	void		GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
278
	void		GetLastDataPos(SCCOL& rCol, SCROW& rRow) const;
278
279
279
	BOOL		TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize );
280
	BOOL		TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize );
Lines 656-661 private: Link Here
656
	BOOL		SearchAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark);
657
	BOOL		SearchAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark);
657
	BOOL		ReplaceAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
658
	BOOL		ReplaceAllStyle(const SvxSearchItem& rSearchItem, ScMarkData& rMark,
658
								ScDocument* pUndoDoc);
659
								ScDocument* pUndoDoc);
660
    bool        SearchAndReplaceEmptyCells(
661
                    const SvxSearchItem& rSearchItem,
662
                    SCCOL& rCol, SCROW& rRow, ScMarkData& rMark,
663
                    String& rUndoStr, ScDocument* pUndoDoc);
664
    bool        SearchRangeForEmptyCell(const ScRange& rRange,
665
                    const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, 
666
                    String& rUndoStr, ScDocument* pUndoDoc);
667
    bool        SearchRangeForAllEmptyCells(const ScRange& rRange, 
668
                    const SvxSearchItem& rSearchItem, ScMarkData& rMark,
669
                    String& rUndoStr, ScDocument* pUndoDoc);
659
670
660
								// benutzen globalen SortParam:
671
								// benutzen globalen SortParam:
661
	BOOL		IsSorted(SCCOLROW nStart, SCCOLROW nEnd);
672
	BOOL		IsSorted(SCCOLROW nStart, SCCOLROW nEnd);
(-)sc/source/core/data/column.cxx (-1 / +18 lines)
Lines 1476-1482 void ScColumn::CopyToColumn(SCROW nRow1, SCROW nRow2, USHORT nFlags, BOOL bMarke Link Here
1476
				}
1476
				}
1477
1477
1478
				if (pNew)
1478
				if (pNew)
1479
					rColumn.Insert(pItems[i].nRow, pNew);
1479
                {
1480
                    // Special case to allow removing of cell instances.  A 
1481
                    // string cell with empty content is used to indicate an
1482
                    // empty cell.
1483
                    if (pNew->GetCellType() == CELLTYPE_STRING)
1484
                    {
1485
                        String aStr;
1486
                        static_cast<ScStringCell*>(pNew)->GetString(aStr);
1487
                        if (aStr.Len() == 0)
1488
                            // A string cell with empty string.  Delete the cell itself.
1489
                            rColumn.Delete(pItems[i].nRow);
1490
                        else
1491
                            // non-empty string cell
1492
                            rColumn.Insert(pItems[i].nRow, pNew);
1493
                    }
1494
                    else
1495
                        rColumn.Insert(pItems[i].nRow, pNew);
1496
                }
1480
			}
1497
			}
1481
		}
1498
		}
1482
	}
1499
	}
(-)sc/source/core/data/table2.cxx (+5 lines)
Lines 923-928 ScBaseCell* ScTable::GetCell( SCCOL nCol, SCROW nRow ) const Link Here
923
	return NULL;
923
	return NULL;
924
}
924
}
925
925
926
void ScTable::GetFirstDataPos(SCCOL& rCol, SCROW& rRow) const
927
{
928
    rCol = 0;
929
    rRow = 0;
930
}
926
931
927
void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
932
void ScTable::GetLastDataPos(SCCOL& rCol, SCROW& rRow) const
928
{
933
{
(-)sc/source/core/data/table6.cxx (+276 lines)
Lines 51-56 Link Here
51
//--------------------------------------------------------------------------
51
//--------------------------------------------------------------------------
52
52
53
53
54
using ::com::sun::star::util::SearchOptions;
55
54
BOOL lcl_GetTextWithBreaks( const ScEditCell& rCell, ScDocument* pDoc, String& rVal )
56
BOOL lcl_GetTextWithBreaks( const ScEditCell& rCell, ScDocument* pDoc, String& rVal )
55
{
57
{
56
	//	TRUE = more than 1 paragraph
58
	//	TRUE = more than 1 paragraph
Lines 672-677 BOOL ScTable::SearchAndReplace(const SvxSearchItem& rSearchItem, Link Here
672
			com::sun::star::util::SearchOptions aSearchOptions = rSearchItem.GetSearchOptions();
674
			com::sun::star::util::SearchOptions aSearchOptions = rSearchItem.GetSearchOptions();
673
			aSearchOptions.Locale = *ScGlobal::pLocale;
675
			aSearchOptions.Locale = *ScGlobal::pLocale;
674
676
677
            if (!aSearchOptions.searchString.getLength())
678
            {
679
                // Search for empty cells.
680
                return SearchAndReplaceEmptyCells(rSearchItem, rCol, rRow, rMark, rUndoStr, pUndoDoc);
681
            }
682
675
			//	#107259# reflect UseAsianOptions flag in SearchOptions
683
			//	#107259# reflect UseAsianOptions flag in SearchOptions
676
			//	(use only ignore case and width if asian options are disabled).
684
			//	(use only ignore case and width if asian options are disabled).
677
			//	This is also done in SvxSearchDialog CommandHdl, but not in API object.
685
			//	This is also done in SvxSearchDialog CommandHdl, but not in API object.
Lines 698-703 BOOL ScTable::SearchAndReplace(const SvxSearchItem& rSearchItem, Link Here
698
	return bFound;
706
	return bFound;
699
}
707
}
700
708
709
bool ScTable::SearchAndReplaceEmptyCells(
710
    const SvxSearchItem& rSearchItem, SCCOL& rCol, SCROW& rRow, ScMarkData& rMark,
711
    String& rUndoStr, ScDocument* pUndoDoc)
712
{
713
    SCCOL nColStart, nColEnd;
714
    SCROW nRowStart, nRowEnd;
715
    GetFirstDataPos(nColStart, nRowStart);
716
    GetLastDataPos(nColEnd, nRowEnd);
717
718
    ScRangeList aRanges;
719
    aRanges.Append(ScRange(nColStart, nRowStart, nTab, nColEnd, nRowEnd, nTab));
720
721
    if (rSearchItem.GetSelection())
722
    {
723
        // current selection only.
724
        if (!rMark.IsMarked() && !rMark.IsMultiMarked())
725
            // There is no selection.  Bail out.
726
            return false;
727
728
        ScRangeList aMarkedRanges, aNewRanges;
729
        rMark.FillRangeListWithMarks(&aMarkedRanges, true);
730
        for (ScRangePtr p = aMarkedRanges.First(); p; p = aMarkedRanges.Next())
731
        {
732
            if (p->aStart.Col() > nColEnd || p->aStart.Row() > nRowEnd)
733
                // This range is outside the data area.  Skip it.
734
                continue;
735
736
            // Shrink the range into data area only.
737
            if (p->aStart.Col() < nColStart)
738
                p->aStart.SetCol(rCol);
739
            if (p->aStart.Row() < nRowStart)
740
                p->aStart.SetRow(rRow);
741
742
            if (p->aEnd.Col() > nColEnd)
743
                p->aEnd.SetCol(nColEnd);
744
            if (p->aEnd.Row() > nRowEnd)
745
                p->aEnd.SetRow(nRowEnd);
746
            
747
            aNewRanges.Append(*p);
748
        }
749
        aRanges = aNewRanges;
750
    }
751
752
    sal_uInt16 nCommand = rSearchItem.GetCommand();
753
    if (nCommand == SVX_SEARCHCMD_FIND || nCommand == SVX_SEARCHCMD_REPLACE)
754
    {
755
        if (rSearchItem.GetBackward())
756
        {
757
            for (ScRangePtr p = aRanges.Last(); p; p = aRanges.Prev())
758
            {
759
                if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr, pUndoDoc))
760
                    return true;
761
            }
762
        }
763
        else
764
        {
765
            for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
766
            {
767
                if (SearchRangeForEmptyCell(*p, rSearchItem, rCol, rRow, rUndoStr, pUndoDoc))
768
                    return true;
769
            }
770
        }
771
    }
772
    else if (nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL)
773
    {
774
        bool bFound = false;
775
        ScMarkData aNewMark(rMark);
776
        aNewMark.ResetMark();
777
        for (ScRangePtr p = aRanges.First(); p; p = aRanges.Next())
778
            bFound |= SearchRangeForAllEmptyCells(*p, rSearchItem, aNewMark, rUndoStr, pUndoDoc);
779
        rMark = aNewMark;
780
        return bFound;
781
    }
782
    return false;
783
}
784
785
bool ScTable::SearchRangeForEmptyCell(
786
    const ScRange& rRange, const SvxSearchItem& rSearchItem, 
787
    SCCOL& rCol, SCROW& rRow, String& rUndoStr, ScDocument* pUndoDoc)
788
{
789
    sal_uInt16 nCmd = rSearchItem.GetCommand();
790
    if (rSearchItem.GetBackward())
791
    {
792
        // backward search
793
        if (rSearchItem.GetRowDirection())
794
        {
795
            // row direction.
796
            SCROW nBeginRow = rRange.aEnd.Row() > rRow ? rRow : rRange.aEnd.Row();
797
            for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
798
            {
799
                SCCOL nBeginCol = rRange.aEnd.Col();
800
                if (nRow == rRow && nBeginCol >= rCol)
801
                    // always start from one cell before the cursor.
802
                    nBeginCol = rCol - (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
803
804
                for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
805
                {
806
                    ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
807
                    if (!pCell)
808
                    {
809
                        // empty cell found.
810
                        rCol = nCol;
811
                        rRow = nRow;
812
                        if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
813
                            rSearchItem.GetReplaceString().Len())
814
                        {
815
                            aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
816
                            rUndoStr = String();
817
                        }
818
                        return true;
819
                    }
820
                }
821
            }
822
        }
823
        else
824
        {
825
            // column direction.
826
            SCCOL nBeginCol = rRange.aEnd.Col() > rCol ? rCol : rRange.aEnd.Col();
827
            for (SCCOL nCol = nBeginCol; nCol >= rRange.aStart.Col(); --nCol)
828
            {
829
                SCROW nBeginRow = rRange.aEnd.Row();
830
                if (nCol == rCol && nBeginRow >= rRow)
831
                    // always start from one cell before the cursor.
832
                    nBeginRow = rRow - (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
833
                for (SCROW nRow = nBeginRow; nRow >= rRange.aStart.Row(); --nRow)
834
                {   
835
                    ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
836
                    if (!pCell)
837
                    {
838
                        // empty cell found.
839
                        rCol = nCol;
840
                        rRow = nRow;
841
                        if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
842
                            rSearchItem.GetReplaceString().Len())
843
                        {
844
                            aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
845
                            rUndoStr = String();
846
                        }
847
                        return true;
848
                    }
849
                }
850
            }
851
        }
852
    }
853
    else
854
    {
855
        // forward search
856
        if (rSearchItem.GetRowDirection())
857
        {
858
            // row direction.
859
            SCROW nBeginRow = rRange.aStart.Row() < rRow ? rRow : rRange.aStart.Row();
860
            for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
861
            {
862
                SCCOL nBeginCol = rRange.aStart.Col();
863
                if (nRow == rRow && nBeginCol <= rCol)
864
                    // always start from one cell past the cursor.
865
                    nBeginCol = rCol + (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
866
                for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
867
                {
868
                    ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
869
                    if (!pCell)
870
                    {
871
                        // empty cell found.
872
                        rCol = nCol;
873
                        rRow = nRow;
874
                        if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
875
                            rSearchItem.GetReplaceString().Len())
876
                        {
877
                            aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
878
                            rUndoStr = String();
879
                        }
880
                        return true;
881
                    }
882
                }
883
            }
884
        }
885
        else
886
        {
887
            // column direction.
888
            SCCOL nBeginCol = rRange.aStart.Col() < rCol ? rCol : rRange.aStart.Col();
889
            for (SCCOL nCol = nBeginCol; nCol <= rRange.aEnd.Col(); ++nCol)
890
            {
891
                SCROW nBeginRow = rRange.aStart.Row();
892
                if (nCol == rCol && nBeginRow <= rRow)
893
                    // always start from one cell past the cursor.
894
                    nBeginRow = rRow + (nCmd == SVX_SEARCHCMD_FIND) ? 1 : 0;
895
                for (SCROW nRow = nBeginRow; nRow <= rRange.aEnd.Row(); ++nRow)
896
                {   
897
                    ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
898
                    if (!pCell)
899
                    {
900
                        // empty cell found.
901
                        rCol = nCol;
902
                        rRow = nRow;
903
                        if (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE &&
904
                            rSearchItem.GetReplaceString().Len())
905
                        {
906
                            aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
907
                            rUndoStr = String();
908
                        }
909
                        return true;
910
                    }
911
                }
912
            }
913
        }
914
    }
915
    return false;
916
}
917
918
bool ScTable::SearchRangeForAllEmptyCells(
919
    const ScRange& rRange, const SvxSearchItem& rSearchItem, ScMarkData& rMark,
920
    String& rUndoStr, ScDocument* pUndoDoc)
921
{
922
    bool bFound = false;
923
    bool bReplace = (rSearchItem.GetCommand() == SVX_SEARCHCMD_REPLACE_ALL) &&
924
                    (rSearchItem.GetReplaceString().Len() > 0);
925
926
    for (SCCOL nCol = rRange.aStart.Col(); nCol <= rRange.aEnd.Col(); ++nCol)
927
    {
928
        if (aCol[nCol].IsEmptyData())
929
        {
930
            // The entire column is empty.  Add the whole column and move on.
931
            rMark.SetMultiMarkArea(
932
                ScRange(nCol, rRange.aStart.Row(), nTab, nCol, rRange.aEnd.Row(), nTab));
933
            bFound = true;
934
935
            if (bReplace)
936
            {
937
                const String& rNewStr = rSearchItem.GetReplaceString();
938
                for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
939
                {    
940
                    aCol[nCol].Insert(nRow, new ScStringCell(rNewStr));
941
                    if (pUndoDoc)
942
                        // TODO: I'm using a string cell with empty content to 
943
                        // trigger deletion of cell instance on undo.  Maybe I
944
                        // should create a new cell type for this?
945
                        pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
946
                }
947
                rUndoStr = String();
948
            }
949
            continue;
950
        }
951
952
        for (SCROW nRow = rRange.aStart.Row(); nRow <= rRange.aEnd.Row(); ++nRow)
953
        {
954
            ScBaseCell* pCell = aCol[nCol].GetCell(nRow);
955
            if (!pCell)
956
            {    
957
                // empty cell found
958
                rMark.SetMultiMarkArea(ScRange(nCol, nRow, nTab));
959
                bFound = true;
960
961
                if (bReplace)
962
                {    
963
                    aCol[nCol].Insert(nRow, new ScStringCell(rSearchItem.GetReplaceString()));
964
                    if (pUndoDoc)
965
                        // TODO: I'm using a string cell with empty content to 
966
                        // trigger deletion of cell instance on undo.  Maybe I
967
                        // should create a new cell type for this?
968
                        pUndoDoc->PutCell(nCol, nRow, nTab, new ScStringCell(String()));
969
                }
970
            }
971
        }
972
    }
973
    return bFound;
974
}
975
976
701
977
702
978
703
979
(-)sc/source/ui/view/tabvwsha.cxx (-3 / +9 lines)
Lines 223-231 void __EXPORT ScTabViewShell::GetState( SfxItemSet& rSet ) Link Here
223
				GetViewData()->GetDocShell()->GetStatePageStyle( *this, rSet, nTab );
223
				GetViewData()->GetDocShell()->GetStatePageStyle( *this, rSet, nTab );
224
				break;
224
				break;
225
225
226
			case SID_SEARCH_ITEM:
226
            case SID_SEARCH_ITEM:
227
				rSet.Put( ScGlobal::GetSearchItem() );
227
            {
228
				break;
228
                const ScMarkData& rMark = GetViewData()->GetMarkData();
229
                SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy.
230
                // Search on current selection if a range is marked.
231
                aItem.SetSelection(rMark.IsMarked());
232
                rSet.Put(aItem);
233
                break;
234
            }
229
235
230
			case SID_SEARCH_OPTIONS:
236
			case SID_SEARCH_OPTIONS:
231
				{
237
				{

Return to issue 49380