Erika Ehrli - Adventures with Office Products & Technologies
MSDN & TechNet: Releasing Office, SharePoint, Exchange & Lync Centers and content for developers and IT professionals.

How to programmatically generate Microsoft Excel AutoFiltered Lists with C#

How to programmatically generate Microsoft Excel AutoFiltered Lists with C#

  • Comments 41

One of my favorite features in Microsoft Excel is AutoFilter. I love to manage lists of data in Excel where I can organize, sort, and filter my information in different columns.

Filtering is a quick and easy way to find and work with a subset of data in a range. A filtered range displays only the rows that meet custom filter criteria defined in a search query or fitler specified for a column. Microsoft Excel provides two commands for filtering ranges: AutoFilter and Advanced Filter. Unlike sorting, filtering does not rearrange a range. Filtering temporarily hides rows you do not want displayed. When Excel filters rows, you can edit, format, chart, and print your range subset without rearranging or moving it. You can learn more about autofiltering here: All About AutoFilter.

The best part is that you can programatically generate autofiltered lists from your managed applications thanks to the extensibility offered by the Microsoft Excel Primary Interop Assembly. You can use the Range.AutoFilter method to filter a list using AutoFilter. The following code sample (C# Console Application) generates an autofiltered list of all the directories and files that belong to given directory path. You can modify the code and send any path that you need.

namespace ErikaEc.OfficeTools.Excel
{
    
using System;
    using 
System.IO;
    using 
Excel Microsoft.Office.Interop.Excel;

    class 
DemoExcelAutoFiltering {
        [STAThread]
        
static void Main(string[] args) {
            DirectoryInfo di 
= new DirectoryInfo(@"C:\Program Files\Microsoft Office\OFFICE11\1033");
            
ExcelFileReport efr = new ExcelFileReport(di);
            
efr.Generate();
        
}
    }

    
public class ExcelFileReport {
        
private object _missing;
        private 
Excel.Workbook _book;
        
Excel.Worksheet _sheet;
        
Excel.Range _rng;
        int 
_row;
        private 
DirectoryInfo _di;
        
ExcelHelper _eh = new ExcelHelper();

        public 
ExcelFileReport(DirectoryInfo di) {
            _di 
di;
            
_missing System.Reflection.Missing.Value;
            
_row 4;
        
}

        
public void DocumentDirectory(DirectoryInfo di) {
            
foreach (DirectoryInfo d in di.GetDirectories()) {
                DocumentDirectory(d)
;
            
}
            
            
foreach (FileInfo f in di.GetFiles()) {
                _row++
;
                
_rng (Excel.Range)_sheet.Cells[_row, "A"];
                
_rng.Value2 di.Name;
                
_rng (Excel.Range)_sheet.Cells[_row, "B"];
                
_rng.Value2 f.FullName;
                
_rng (Excel.Range)_sheet.Cells[_row, "C"];
                
_rng.Value2 f.Name;
                
_rng (Excel.Range)_sheet.Cells[_row, "D"];
                
_rng.Value2 f.Length;
                
_rng (Excel.Range)_sheet.Cells[_row, "E"];
                
_rng.Value2 f.Extension;
                
_rng (Excel.Range)_sheet.Cells[_row, "F"];
                
_rng.Value2 f.LastWriteTime.ToLongDateString();
            
}
        }
        
        
public void Generate(){
            
string caption "File Analysis Results";
            string 
heading1 "File Analysis Report for Folder " + _di.FullName;
            
_book _eh.Create(caption, heading1);
            
_sheet ((Excel.Worksheet)_book.ActiveSheet);
            
WriteTableHeader();
            
DocumentDirectory(_di);
            
SetAutoFilter();
            
_eh.Close();
        
}

        
private void SetAutoFilter(){
            
string lastrow "F" + _row.ToString();
            
_rng ((Excel.Worksheet)_book.ActiveSheet).get_Range("A4", lastrow);
            
_rng.AutoFilter(1, _missing, Excel.XlAutoFilterOperator.xlAnd, _missing, true);
            
_rng.Borders.LineStyle Excel.XlLineStyle.xlContinuous;
        
}
    
        
public void WriteTableHeader(){
            _rng 
((Excel.Worksheet)_book.ActiveSheet).get_Range("A4""H3");
            
_rng.Font.Bold = true;
            
_rng.EntireRow.Font.Bold = true;

            
_rng (Excel.Range)_sheet.Cells[_row, "A"];
            
_rng.Value2 "Parent Directory";
            
_rng (Excel.Range)_sheet.Cells[_row, "B"];
            
_rng.Value2 "Full Path";
            
_rng (Excel.Range)_sheet.Cells[_row, "C"];
            
_rng.Value2 "File Name";
            
_rng (Excel.Range)_sheet.Cells[_row, "D"];
            
_rng.Value2 "Size";
            
_rng (Excel.Range)_sheet.Cells[_row, "E"];
            
_rng.Value2 "Type";
            
_rng (Excel.Range)_sheet.Cells[_row, "F"];
            
_rng.Value2 "Last Modified";

            
_sheet.Columns.ColumnWidth 30;
        
}
    }

    
class ExcelHelper {
        
private Excel.Application _excelApplication;
        
        public 
ExcelHelper() {
            _excelApplication 
= new Excel.Application();
        
}

        
public Excel.Workbook Create(string caption, string heading1) {
            
try {
                _excelApplication.Caption 
caption;
                
_excelApplication.ScreenUpdating = false;
                
_excelApplication.Visible = false;

                
Excel.Workbook book _excelApplication.Workbooks.Add(Excel.XlSheetType.xlWorksheet);
                
Excel.Worksheet sheet (Excel.Worksheet)book.ActiveSheet;

                
Excel.Range r (Excel.Range)sheet.Cells[1"A"];
                
r.Value2 heading1;
                
r.EntireRow.Font.Bold = true;

                return 
book;

            
}
            
catch (Exception ex) {
                
throw (ex);
            
}
        }

        
public void Close() {
            _excelApplication.ScreenUpdating 
= true;
            
_excelApplication.Visible = true;
            
_excelApplication.DisplayAlerts = true;

            if 
(_excelApplication != null) {
                _excelApplication.Quit()
;
                
_excelApplication = null;
                
GC.Collect();
                
GC.WaitForPendingFinalizers();
                
GC.Collect();
                
GC.WaitForPendingFinalizers();
            
}
        }
    }
}

Run this application and give it a try!

Leave a Comment
  • Please add 7 and 4 and type the answer here:
  • Post
  • Hi erika,
    I've a problem that's still related with your topics and it makes me so stressfull ... i developed infopath form and C# as codebehind. While I send a value to the excel that was created before on your programming way is still OK. But, if I try to read from Excel cell from infopath code always display error:
    Exception from HRESULT: 0x800A03EC.
    at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
    at Microsoft.Office.Interop.Excel.Range.get_Item(Object RowIndex, Object ColumnIndex)

    Do you know about this error??

    thank you very much ...
    Rahman Hadi(rahman_hadi@fmi.com)
  • Hi Rahman,
    I have not seen that error, but I made some research and I learned that when you are working with Excel 2003 and other Visual Studio solutions you might need to consider globalization and localization aspects. I found some articles that might help:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_wrcore/html/wrconGlobalizingLocalizingOfficeSolutions.asp
    http://www.devx.com/OfficeProDev/Article/29507?trk=DXRSS_LATEST
    http://blogs.msdn.com/eric_carter/archive/2005/06/15/429515.aspx
  • One way to workaround the problem of using an English version of Excel with a culture ID other than English, is to add these lines in your code:

    System.Globalization.CultureInfo enUS = new System.Globalization.CultureInfo("en-US");
    System.Threading.Thread.CurrentThread.CurrentCulture = enUS;

    Fernando Ferreira (fferre)
    Microsoft Consulting Services
  • Hello,

    I have an Excel template with inserted database query. When I open a template programically from my application, I want to set AutoFilter according to values that user enters in my application. The code is as follows:

    // open template, then:
    Excel.Range _range = (Excel.Range)sheet.get_Range("A3", "Q3");
    _range.AutoFilter(3, "=Petras", Excel.XlAutoFilterOperator.xlAnd, vk_missing, true);
    _range.AutoFilter(5, "<>Jonas", Excel.XlAutoFilterOperator.xlAnd, vk_missing, true);
    // show worksheet

    the funny thing is that AutoFiltering works 4 times out of 5 - sometimes autofiltering is not set though no errors are displayed. Is that some kind if bug or my code isn't correct?

    Thank you very much in advance.
  • I am generating an XLS file via the PIAs using JSCRIPT .NET. I have carefully called Marshall.Release on each object and have even included a call to GC.Collect. EXCEL.EXE refuses to quit ... I don't know what to do. Can you help?
  • You have to release ALL objects that you created using excel. Then call garbage collection.

    Sample code below i am releasing each object using ReleaseComObject function.

    object delete = oSheet;   // assign worksheet as object
    ReleaseComObject(ref delete); //delete worksheet
    delete = oWB; // assign workbook as object
    ReleaseComObject(ref delete); // delete workbook
    delete = oXL;  // assign excel application as obejct
    ReleaseComObject(ref delete); //delete excel

    GC.Collect();


    function
    ----------------
    private void ReleaseComObject(ref Object o)
    {
        while (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0);
    }
  • I got the 0x800A03EC error too.
    I tried the Globalization fix, but that didn't work (I didn't really expect it to - as far as I'm aware, there's no difference in the way the Brits and the Americans reference Excel cells and columns!

    I found I got the error when selecting a range using oWB.Columns[1,2]. I used Columns because I wanted to set the ColumnWidth.

    I change it to oWB.Cells[1,2] and it worked fine. I guess .ColumnWidth (and no doubt .AutoFilter) don't really care HOW the Range was created, just that it is a range!
  • i wanted to know if there is any online resource available where i can learn more abt the excel 11.0 object library. something that starts from basics and moves on to a more advanced level
  • Hi Sina,

    You can find the VBA reference for Excel 11.0 here:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbaxl11/html/xltocOMMap_HV01049651.asp

    You can find more VBA reference for other products and versions here:

    http://msdn.microsoft.com/office/reference/vba/default.aspx
  • I have an xls file created and i want toopen it add new sheet in existing file and save the xls file is  there any one who can help me in this?

  • Hi Erika,

    I am developing an Excel Add-In in Visual Studio 2005 (C#) for Excel XP and higher.

    I read somewhere that I need to explicitly release all objects even the Range object that I get from get_Range() method.

    What else need to be released in an Add-In ?

    regards

    Abhimanyu Sirohi

  • I am having problems with excel reference in my .NET project.

    I added reference to Excel object in my .NET application by including Excel 11.0 object library. My app worked fine until the following line was added to one of the classes where the excel operations are performed.

    using Excel = Microsoft.Office.Interop.Excel;

    When the above line is added the build throws error in my machine saying

    I:\Transform\Spreadsheet\ExcelLoader.cs(12): Namespace '' already contains a definition for 'Excel'

    If the above line is removed, it works fine in my machine, but throws a different error in my colleague's machine.

    Can somebody help me in telling me under what circumstance the above line should be added, and why the .NET environment in my machine is complaining about the line.

    Any help is greatly appreciated.

    -Siya

  • Siya,

    This article may help

    http://support.microsoft.com/kb/823981

    Also Office XP PIA's are available at

    http://www.microsoft.com/downloads/details.aspx?FamilyId=C41BD61E-3060-4F71-A6B4-01FEBA508E52&displaylang=en

    regards

  • Hi Erika,

    I am developing an Excel Add-In in Visual Studio 2005 (C#) for Excel 2007.

    I would like to know how to dynamically remove the Excel Cells in Memory.

    Thannks,

    Ram

  • Hi,

    I m facing one problem

    How to Catch  Any Excel File Which user opens..

    I want to catch that file from my program and if any changes made in that file then i want to save those changes as well as old changes also i want ...

    I want to make program in C#.NET or ASP.NET  can you help me about this?

    Contact me on:

    nileshupadhyay10582@gmail.com

    Thanks in advance

Page 1 of 3 (41 items) 123