views:

318

answers:

1

I am running into an issue with Excel 2007 via VSTO 3.0. In my project, I need to shuffle columns around occasionally. Normally, this works fine but I have recently found that an issue arises when the data is filtered and the fitlered data is non-contiguous.

For example, using this data set:

Ohio        Eastern
Kentucky    Eastern
Illinois    Central
California  Pacific
Florida     Eastern

If the filter on column two excludes either Pacific or Central, the following code produces an error.

ListObject table = FindReportTable();
// Get data to shuffle around.
ListColumn tempColumn = table.ListColumns.Add(missing);
Range range1 = table.ListColumns[column1].Range;
Range range2 = table.ListColumns[column2].Range;
Range tempRange = tempColumn.Range;
// Swap the rows.
range1.Copy(tempRange); // This is where an error is thrown.
range2.Copy(range1);
tempRange.Copy(range2);
tempColumn.Delete();

The error thrown is a System.Runtime.InteropServices.COMException with an error code of -2146827284 and message "That command cannot be used on multiple selections".

I have tried many things and none seem to work completely. If I use table.AutoFilter.ShowAllData(), I can continue with no problems, but I have then cleared the user's filters and cannot get them back with table.AutoFilter.ApplyFilter() as I assumed.

I cannot reliably store and recreate the filters for two reasons: one, iterating through table.AutoFilter.Filters and storing the filter's data can cause problems if the dataset in the filter is too large. Referring to my example data, if the filter was to exclude Central from column 2, attempting to retrieve the filter's information causes an interop error. Second, to recreate the filter, I need to know what row the filter was originally on to pass into the table.Range.AutoFilter(object, object, XlFilterOperator, object, object) method.

I have been banging my head against this for too long now, and can't seem to find a solution in my own head or on the vast internets. Any help would be much appreciated.

+1  A: 

I would look into removing and recreating the filters. If you're seeing problems, then you should fix those problems.

Look at the ListObject.AutoFilter.Filters collection.

Look here for more information.

Gabriel McAdams
That's what I've been trying to do, but can't figure out how to do it. I've tried a few ways that seem like they should result in this such as `AutoFilter.ShowAllData()` and `AutoFilter.ApplyFilter()`, but it doesn't work.
Jake Basile
I've also tried what I believe you are hinting at: saving the filter criteria, clearing them, reordering as I need to, and then recreating each filter. This would be an ideal solution, but for the reasons in the second paragraph from the bottom of the question, it doesn't work. If there was a way to get the column that the filter is on, and also get the criteria without an exception if there dataset is large it would work perfectly.
Jake Basile
Look at this link. It does exactly what you're trying to accomplish (using VBA - it shouldn't be too hard for you to convert) - http://msdn.microsoft.com/en-us/library/bb210085.aspx
Gabriel McAdams
That link led me in the right direction. I was able to find out two things about the Filter object that were key: 1. Criteria2 can be missing, but requesting it if it is missing leads to an Exception. 2. Operator can be 0, even though that isn't really a valid value. If you change it to xlFilterValues it seems to work fine on recreation.Thanks for the help, the problem's solved now.
Jake Basile
I'm glad it worked out.
Gabriel McAdams