![]() |
Defining a discontiguous Range object
I have a spreadsheet column that could include empty cells, zero values,
strings, and non-zero values. I would like to define a Range object that references only the non-zero values. I'd prefer not to loop. Ideally, the method also would allow me to define a Range based on other criteria, like cells with values greater than 100, or whatever. This is easy to do in an array formula in a spreadsheet, with something like: =Sum(If(Foo100,Foo,0)) I've been playing around with FormulaArray. But I don't see a clean way to define a range object based on this property. Does anyone have any ideas? Thanks. Charley |
Defining a discontiguous Range object
Charley,
Take a look at the "SpecialCells" method in ExcelVB help. It does what you want, except for picking out particular values. Regards, Jim Cone San Francisco, CA "Charley Kyd" wrote in message ... I have a spreadsheet column that could include empty cells, zero values, strings, and non-zero values. I would like to define a Range object that references only the non-zero values. I'd prefer not to loop. Ideally, the method also would allow me to define a Range based on other criteria, like cells with values greater than 100, or whatever. This is easy to do in an array formula in a spreadsheet, with something like: =Sum(If(Foo100,Foo,0)) I've been playing around with FormulaArray. But I don't see a clean way to define a range object based on this property. Does anyone have any ideas? Thanks. Charley |
Defining a discontiguous Range object
Jim,
Unless I'm missing something, I don't think SpecialCells will do what I want, without looping. If someone didn't offer a better solution, I had thought about looping through the data once, hiding each row that I don't want in my Range object, and then using SpecialCells to return the discontiguous range of the unhidden cells that I do want. That solution would be rather fast to code and fast to execute. But I was hoping for something more direct. Any other ideas? Charley "Jim Cone" wrote in message ... Charley, Take a look at the "SpecialCells" method in ExcelVB help. It does what you want, except for picking out particular values. Regards, Jim Cone San Francisco, CA "Charley Kyd" wrote in message ... I have a spreadsheet column that could include empty cells, zero values, strings, and non-zero values. I would like to define a Range object that references only the non-zero values. I'd prefer not to loop. Ideally, the method also would allow me to define a Range based on other criteria, like cells with values greater than 100, or whatever. This is easy to do in an array formula in a spreadsheet, with something like: =Sum(If(Foo100,Foo,0)) I've been playing around with FormulaArray. But I don't see a clean way to define a range object based on this property. Does anyone have any ideas? Thanks. Charley |
Defining a discontiguous Range object
Charley,
Loops are a very useful tool and easy to write. If written properly they will execute very fast. With that said, code similar to the following will reduce the searching/looping significantly... '---------------------------------------------------------------- Set FirstRng = MyColumn.SpecialCells(xlCellTypeFormulas) Set SecondRng = MyColumn.SpecialCells(xlCellTypeConstants) 'Union method generates an error if a range is nothing If FirstRng Is Nothing Then Set FirstRng = SecondRng ElseIf SecondRng Is Nothing Then Set SecondRng = FirstRng End If Set FinalRange = Application.Union(FirstRng, SecondRng) '--------------------------------------------------------------- Now run your loop thru "FinalRange" Regards, Jim Cone San Francisco, CA ==================================== "Charley Kyd" wrote in message ... Jim, Unless I'm missing something, I don't think SpecialCells will do what I want, without looping. If someone didn't offer a better solution, I had thought about looping through the data once, hiding each row that I don't want in my Range object, and then using SpecialCells to return the discontiguous range of the unhidden cells that I do want. That solution would be rather fast to code and fast to execute. But I was hoping for something more direct. Any other ideas? Charley "Jim Cone" wrote in message ... Charley, Take a look at the "SpecialCells" method in ExcelVB help. It does what you want, except for picking out particular values. Regards, Jim Cone San Francisco, CA - snip - |
Defining a discontiguous Range object
Sub testit()
Dim rngSource As Range, rngFilter As Range, rng As Range, dblMySum As Double Set rngSource = Range("A1:A1000") For Each rng In rngSource If IsNumeric(rng.Value) And rng.Value = 500 Then If rngFilter Is Nothing Then Set rngFilter = rng Else Set rngFilter = Union(rngFilter, rng) End If End If Next rngFilter.Select For Each rng In rngFilter: dblMySum = dblMySum + rng.Value: Next MsgBox dblMySum End Sub "Charley Kyd" wrote in message ... I have a spreadsheet column that could include empty cells, zero values, strings, and non-zero values. I would like to define a Range object that references only the non-zero values. I'd prefer not to loop. Ideally, the method also would allow me to define a Range based on other criteria, like cells with values greater than 100, or whatever. This is easy to do in an array formula in a spreadsheet, with something like: =Sum(If(Foo100,Foo,0)) I've been playing around with FormulaArray. But I don't see a clean way to define a range object based on this property. Does anyone have any ideas? Thanks. Charley |
Defining a discontiguous Range object
Thanks, Jim.
Charley "Jim Cone" wrote in message ... Charley, Loops are a very useful tool and easy to write. If written properly they will execute very fast. With that said, code similar to the following will reduce the searching/looping significantly... '---------------------------------------------------------------- Set FirstRng = MyColumn.SpecialCells(xlCellTypeFormulas) Set SecondRng = MyColumn.SpecialCells(xlCellTypeConstants) 'Union method generates an error if a range is nothing If FirstRng Is Nothing Then Set FirstRng = SecondRng ElseIf SecondRng Is Nothing Then Set SecondRng = FirstRng End If Set FinalRange = Application.Union(FirstRng, SecondRng) '--------------------------------------------------------------- Now run your loop thru "FinalRange" Regards, Jim Cone San Francisco, CA ==================================== "Charley Kyd" wrote in message ... Jim, Unless I'm missing something, I don't think SpecialCells will do what I want, without looping. If someone didn't offer a better solution, I had thought about looping through the data once, hiding each row that I don't want in my Range object, and then using SpecialCells to return the discontiguous range of the unhidden cells that I do want. That solution would be rather fast to code and fast to execute. But I was hoping for something more direct. Any other ideas? Charley "Jim Cone" wrote in message ... Charley, Take a look at the "SpecialCells" method in ExcelVB help. It does what you want, except for picking out particular values. Regards, Jim Cone San Francisco, CA - snip - |
Defining a discontiguous Range object
Hi Charley,
Thank you for posting in MSDN managed newsgroup! From my understanding to this issue, you are going to find one quick way to filter some values from the excel worksheet. If all the values in the cells are not sorted, you will need to use Loop to pick up the values you want. So far as I know in this scenario, the quickest way for you is to use SpecialCell method as Jim has suggested. For the usage of SpecialCell mentioned in your reply, I agree with that you should hide some cells so that SpecialCell can filter the value for you. Furthermore, if all the values has been sorted, it will be simple for you to obtain the specified value. I'd suggest you can sort the values during the creation of the worksheet and then it will be very fast for you to locate these special values. Please feel free to let me know if you have any further questions. Does this answer your question? Thank you for using Microsoft NewsGroup! Wei-Dong Xu Microsoft Product Support Services Get Secure! - www.microsoft.com/security This posting is provided "AS IS" with no warranties, and confers no rights. |
Defining a discontiguous Range object
Because nobody could suggest a non-looping way to grab a discontiguous
range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
Dave,
Thanks for the idea. But as you say, it doesn't allow for non-zero filtering. It doesn't deal with possible error values in the range. And because of past bugs and performance problems, I tend to shy away from using temporary workbooks or worksheets. I'm still looking for a more powerful way to define a range object. Charley "Dave Peterson" wrote in message ... Tom Ogilvy posted a pretty neat solution to a similar question that created a new temporary worksheet, copied values there, and then manipulated some stuff on that temporary worksheet. Here's a version of that routine: Option Explicit Function NumericNonZeroRng(rng As Range) As Range Dim wks As Worksheet Dim myArea As Range Dim myNewRng As Range Set wks = Worksheets.Add With wks .Range(rng.Address).Value = rng.Value On Error Resume Next 'get rid of text cells .Cells.SpecialCells(xlCellTypeConstants, xlTextValues).ClearContents 'get rid of zero cells .UsedRange.Replace what:=0, replacement:="", lookat:=xlWhole Set myNewRng = Nothing Set myNewRng = .Cells.SpecialCells(xlCellTypeConstants) On Error GoTo 0 End With If myNewRng Is Nothing Then Set NumericNonZeroRng = Nothing Else Set NumericNonZeroRng = rng.Parent.Range(myNewRng.Address) End If Application.DisplayAlerts = False wks.Delete Application.DisplayAlerts = True End Function And to test it. Sub testme01() Dim myRng As Range Dim myNonZeroRng As Range Application.ScreenUpdating = False With ActiveSheet Set myRng = ActiveSheet.Range("a1").CurrentRegion Set myNonZeroRng = NumericNonZeroRng(myRng) If myNonZeroRng Is Nothing Then MsgBox "none found" Else myNonZeroRng.Select 'for example End If End With Application.ScreenUpdating = True End Sub The bad thing is that I don't see a way to modify it to keep cells based on a criterion like 100 (without looping). Maybe inserting a new row, applying a filter based the opposite of your criteria, and clearing the visible cells, then doing the next column (and so forth). Charley Kyd wrote: I have a spreadsheet column that could include empty cells, zero values, strings, and non-zero values. I would like to define a Range object that references only the non-zero values. I'd prefer not to loop. Ideally, the method also would allow me to define a Range based on other criteria, like cells with values greater than 100, or whatever. This is easy to do in an array formula in a spreadsheet, with something like: =Sum(If(Foo100,Foo,0)) I've been playing around with FormulaArray. But I don't see a clean way to define a range object based on this property. Does anyone have any ideas? Thanks. Charley -- Dave Peterson |
Defining a discontiguous Range object
I'm curious. How is this better than Rob van Gelder's solution? Or
for that matter Dave Peterson's suggestion, which doesn't modify the user's selection of visible / hidden rows? -- Regards, Tushar Mehta, MS MVP -- Excel www.tushar-mehta.com Excel, PowerPoint, and VBA add-ins, tutorials Custom MS Office productivity solutions In article , says... Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
What's wrong with looping?
- Jon ------- Jon Peltier, Microsoft Excel MVP Peltier Technical Services http://PeltierTech.com/Excel/Charts/ _______ Charley Kyd wrote: Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
Tushar,
I haven't tested Rob's solution; I read it after I had written my own. But because it requires two loops, and because it performs a Union for each cell that passes the filter, it feels like it would be slower than mine. The key to my approach was that no action was necessary for each cell within a contiguous group of cells. But maybe I'm wrong; I often am. Charley "Tushar Mehta" wrote in message om... I'm curious. How is this better than Rob van Gelder's solution? Or for that matter Dave Peterson's suggestion, which doesn't modify the user's selection of visible / hidden rows? -- Regards, Tushar Mehta, MS MVP -- Excel www.tushar-mehta.com Excel, PowerPoint, and VBA add-ins, tutorials Custom MS Office productivity solutions In article , says... Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
Jon,
What's wrong with looping? Speed. Because the user will work interactively with the data, I'm looking for an instantaneous response. I was assuming that a non-looping solution would tend to be faster than a looping solution. I should have emphasized *speed* in my original post. Charley "Jon Peltier" wrote in message ... What's wrong with looping? - Jon ------- Jon Peltier, Microsoft Excel MVP Peltier Technical Services http://PeltierTech.com/Excel/Charts/ _______ Charley Kyd wrote: Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
Charley,
If you want speed, then I recommend you find a way to measure it. Here is a Microsoft KB article which will assist: HOWTO: Use QueryPerformanceCounter to Time Code http://support.microsoft.com/default.aspx?scid=kb;[LN];172338 Rob "Charley Kyd" wrote in message ... Jon, What's wrong with looping? Speed. Because the user will work interactively with the data, I'm looking for an instantaneous response. I was assuming that a non-looping solution would tend to be faster than a looping solution. I should have emphasized *speed* in my original post. Charley "Jon Peltier" wrote in message ... What's wrong with looping? - Jon ------- Jon Peltier, Microsoft Excel MVP Peltier Technical Services http://PeltierTech.com/Excel/Charts/ _______ Charley Kyd wrote: Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
Defining a discontiguous Range object
Thanks, Rob. I hadn't seen that article before.
For years, I've relied on the Timer function in a nested loop. I like using Timer because it takes less than a minute to write a performance-testing program from scratch after the competing routines have been written. To illustrate, if I want to compare the performance of two approaches, I'll loop through one approach for, say, ten thousand loops. I'll add zeros to the loop counter until the total time is about ten seconds. Then I'll loop through the other approach for the same number of passes. Comparing the number of seconds returned by Timer for each of the two tests gives me an adequate guide. Although the article says that Timer only has a one-second resolution, it appears to report reliable times to at least three decimal places. Even that precision isn't needed, however, because one approach tends to be several times faster than the other. If two competing approaches take about the same time to execute many thousands of passes, then I'll choose the alternative that's shortest and easiest to understand. There's a lot to be said for the KISS philosophy of programming. All the best, Charley "Rob van Gelder" wrote in message ... Charley, If you want speed, then I recommend you find a way to measure it. Here is a Microsoft KB article which will assist: HOWTO: Use QueryPerformanceCounter to Time Code http://support.microsoft.com/default.aspx?scid=kb;[LN];172338 Rob "Charley Kyd" wrote in message ... Jon, What's wrong with looping? Speed. Because the user will work interactively with the data, I'm looking for an instantaneous response. I was assuming that a non-looping solution would tend to be faster than a looping solution. I should have emphasized *speed* in my original post. Charley "Jon Peltier" wrote in message ... What's wrong with looping? - Jon ------- Jon Peltier, Microsoft Excel MVP Peltier Technical Services http://PeltierTech.com/Excel/Charts/ _______ Charley Kyd wrote: Because nobody could suggest a non-looping way to grab a discontiguous range, the looping version that I came up with is shown below. Because it hides unwanted cells in blocks, and because Rows.Hidden = True is a fast operation, this probably runs about as quickly as anything. Charley ''================================================ ========================== ===== '' Program: NonZeroRange '' Desc: Returns a discontiguous range of all cells with a non-zero value '' found in a single-column range '' Called by: '' Call: NonZeroRange(rngData) '' Arguments: rngData--The source range '' Comments: This could be modified to use more sophisticated filters. '' Changes--------------------------------------------------------------------- - '' Date Programmer Change '' 12/25/03 Charley Kyd Written ''================================================ ========================== ===== Private Function NonZeroRange(rngData As Range) As Range Dim rngCur As Range, rngStart As Range, bDoingZeros As Boolean Dim gVal As Single bDoingZeros = False ''Make sure all rows begin as unhidden rngData.Rows.Hidden = False For Each rngCur In rngData ''Trap error values. (Note: Using IIf doesn't work because it ''calculates both results, generating an error value.) If IsError(rngCur) Then gVal = 0 Else gVal = Val(rngCur) ''If this is an item to hide... If gVal = 0 Then ''If this is the first zero found in a block If Not bDoingZeros Then bDoingZeros = True Set rngStart = rngCur End If ''If this is a non-zero value Else ''If we're done with a block of zeros... If bDoingZeros Then ''Hide the current block, ending with the previous cell Range(rngStart, rngCur.Offset(-1, 0)).Rows.Hidden = True bDoingZeros = False End If End If Next rngCur ''If the range ends with a zero... If bDoingZeros Then Range(rngStart, rngData.SpecialCells(xlCellTypeLastCell)).Rows.Hid den = True End If ''Define the range of searched-for values Set NonZeroRange = rngData.SpecialCells(xlCellTypeVisible) ''Unhide the range rngData.Rows.Hidden = False End Function |
All times are GMT +1. The time now is 04:26 PM. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
ExcelBanter.com