2015-09-22 28 views
5

Sto provando a impostare un filtro su una colonna. Questo è il modo in cui l'ho fatto in Interop:Aggiunta di un filtro automatico specifico su una colonna

private void CheckMasterFile(string path) { 
    var xlApp = new Excel.Application(); 
    var xlWorkbook = xlApp.Workbooks.Open(path); 
    Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[1]; 

    foreach (var project in projects) { 
     if (string.IsNullOrEmpty(project.ProjectID.Value)) { 
      continue; 
     } 

     var xlRange = xlWorksheet.UsedRange; 
     if (xlWorksheet.AutoFilter != null) { 
      xlWorksheet.AutoFilterMode = false; 
     } 
     xlRange.AutoFilter(Field: 2, Criteria1: project.ProjectID.Value); 
     var result = xlRange.SpecialCells(Excel.XlCellType.xlCellTypeVisible, Type.Missing);//only shows filtered values 
     double sum = 0; 

     foreach (Excel.Range row in result.Rows) { 
      if (row.Cells[2, 2].Value2() != null) { 
       if (!NOT_ALLOWED_RUBRIQUES.Contains((string)row.Cells[2, 8].Value2())) {//check if rubrique is allowed or not 
        //finish method 
       } 
      } 
     } 
    } 
    xlWorkbook.Close(SaveChanges: false); 
    xlApp.Quit(); 
} 

Ma l'unico modo che posso fare qualcosa con il filtro automatico in EPPlus è quello di abilitare o disabilitare, non filtrare una colonna su un valore specifico. Qualcosa di simile a questo:

sheet.Cells["A RANGE HERE"].AutoFilter = true; 

Quindi quello che sto cercando di realizzare è quello di filtrare un file enorme di Excel su un valore specifico e poi mostrare solo le righe con quei valori.

+0

Quello che ho capito è, si vuoi che l'Excel generato abbia solo i dati filtrati, giusto? Ad esempio: se hai 1000 record e il tuo filtro corrisponde solo a 50 righe, l'Excel generato dovrebbe avere solo 50 righe. Sto ottenendo correttamente? –

+0

beh, non esattamente un nuovo file generato, il file che sto aprendo contiene oltre 1000 record. Voglio applicare un filtro su quel file in modo che mi mostri solo 50 record e crei un ciclo su quelle celle invece di scorrere l'intero file e controllare se ciascuna cella in quel ciclo è uguale a projectID (project.ProjectID.Value) – Edward

risposta

7

Se ho capito cosa stai chiedendo, non è questo l'intento di EPPlus. È pensato per generare il file excel come endpoint. Quello che stai cercando di fare sembra effettivamente utilizzare Excel come strumento di analisi.

Se si desidera realmente applicare un filtro a una colonna per l'output, quindi è necessario farlo manualmente poiché EPPlus non applica i filtri in modo nativo. Quindi qualcosa del genere (ho dovuto occuparmene io stesso). Ma l'onere è ancora su di voi (il generatore) per eseguire effettivamente l'analisi - che lo scorso linq query in questo caso:

[TestMethod] 
public void AutoFilter_Test() 
{ 
    //http://stackoverflow.com/questions/32723483/adding-a-specific-autofilter-on-a-column 

    //Throw in some data 
    var datatable = new DataTable("tblData"); 
    datatable.Columns.AddRange(new[] { new DataColumn("Col1", typeof(int)), new DataColumn("Col2", typeof(int)), new DataColumn("Col3", typeof(object)) }); 

    for (var i = 0; i < 10; i++) 
    { 
     var row = datatable.NewRow(); row[0] = i; row[1] = i * 10;row[2] = Path.GetRandomFileName(); 
     datatable.Rows.Add(row); 
    } 

    //Create a test file 
    var fi = new FileInfo(@"c:\temp\autofilter.xlsx"); 
    if (fi.Exists) 
     fi.Delete(); 

    using (var pck = new ExcelPackage(fi)) 
    { 
     var worksheet = pck.Workbook.Worksheets.Add("Sheet1"); 
     worksheet.Cells.LoadFromDataTable(datatable, true); 

     var range = worksheet.Cells["A1:C10"]; 
     range.AutoFilter = true; 

     pck.Save(); 
    } 

    //Needed prior save in order for the XML to be generated 
    using (var pck = new ExcelPackage(fi)) 
    { 
     var worksheet = pck.Workbook.Worksheets.First(); 

     //Get reference to the worksheet xml for proper namespace 
     var xdoc = worksheet.WorksheetXml; 
     var nsm = new XmlNamespaceManager(xdoc.NameTable); 
     nsm.AddNamespace("default", xdoc.DocumentElement.NamespaceURI); 

     //Create the filters themselves 
     var filter1 = xdoc.CreateNode(XmlNodeType.Element, "filter", xdoc.DocumentElement.NamespaceURI); 
     var att = xdoc.CreateAttribute("val"); 
     att.Value = "40"; 
     filter1.Attributes.Append(att); 

     var filter2 = xdoc.CreateNode(XmlNodeType.Element, "filter", xdoc.DocumentElement.NamespaceURI); 
     att = xdoc.CreateAttribute("val"); 
     att.Value = "50"; 
     filter2.Attributes.Append(att); 

     //Add filters to the collection 
     var filters = xdoc.CreateNode(XmlNodeType.Element, "filters", xdoc.DocumentElement.NamespaceURI); 
     filters.AppendChild(filter1); 
     filters.AppendChild(filter2); 

     //Create the parent filter container 
     var filterColumn = xdoc.CreateNode(XmlNodeType.Element, "filterColumn", xdoc.DocumentElement.NamespaceURI); 
     att = xdoc.CreateAttribute("colId"); 
     att.Value = "1"; 
     filterColumn.Attributes.Append(att); 
     filterColumn.AppendChild(filters); 

     //Now add it to the autoFilters node 
     var autoFilter = xdoc.SelectSingleNode("/default:worksheet/default:autoFilter", nsm); 
     autoFilter.AppendChild(filterColumn); 

     //Have to manually hide rows based on criteria 
     worksheet.Cells 
      .Where(cell => 
       cell.Address.StartsWith("B") 
       && cell.Value is double 
       && (double) cell.Value != 40d 
       && (double) cell.Value != 50d) 
      .Select(cell => cell.Start.Row) 
      .ToList() 
      .ForEach(r => worksheet.Row(r).Hidden = true); 

     pck.Save(); 
    } 
} 

USCITA

enter image description here

Problemi correlati