简体   繁体   中英

How to set filters to header columns and set auto width

I'm trying to edit existing code that works, and to add some features such as:

  • Auto width (column width is determined by the longest text in that column)
  • Header filters (put filters to all header columns that are presented)

Sources where I looked for this solutions:

But, it seems to me that these implementations can not be applied to my case, because I have different input parameters.

Code looks like:

protected ActionResult ExportObjectList(List<string> exportColumns, List<Dictionary<string, string>> valueList, string fileName)
{
    string exportFileName = fileName.IndexOf("xlsx") < 0 ? fileName + ".xlsx" : fileName;
    byte[] fileBytesArray = ExportDataToExcell(exportColumns, valueList, exportFileName);
    return File(fileBytesArray, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", exportFileName);
}
private byte[] ExportDataToExcell(List<string> exportColumns, List<Dictionary<string, string>> valueList, string fileName)
{
    MemoryStream memoryStream = new MemoryStream();
    using (SpreadsheetDocument document = SpreadsheetDocument.Create(memoryStream, SpreadsheetDocumentType.Workbook))
    {
        WorkbookPart workbookPart = document.AddWorkbookPart();
        WorksheetPart sheetPart = document.WorkbookPart.AddNewPart<WorksheetPart>();
        SheetData sheetData = new SheetData();
        sheetPart.Worksheet = new Worksheet(sheetData);

        document.WorkbookPart.Workbook = new Workbook();

        document.WorkbookPart.Workbook.Sheets = new Sheets();

        Sheets sheets = document.WorkbookPart.Workbook.GetFirstChild<Sheets>();
        string relationshipId = document.WorkbookPart.GetIdOfPart(sheetPart);

        uint sheetId = 1;
        if (sheets.Elements<Sheet>().Count() > 0)
        {
            sheetId =
                sheets.Elements<Sheet>().Select(s => s.SheetId.Value).Max() + 1;
        }

        Sheet sheet = new Sheet() { Id = relationshipId, SheetId = sheetId, Name = "ExportDataSheet" };
        sheets.Append(sheet);

        Row headerRow = new Row();

        foreach (string headerCell in exportColumns)
        {

            Cell keyCell = new Cell();
            keyCell.DataType = CellValues.String;
            keyCell.CellValue = new CellValue(headerCell);
            headerRow.AppendChild(keyCell);
        }

        sheetData.AppendChild(headerRow);
        //AutoFilter autoFilter = new AutoFilter() { Reference = "A1:K9" };
        foreach (Dictionary<string, string> itemList in valueList)
        {
            Row newRow = new Row();
            foreach (string headerCell in exportColumns)
            {
                //foreach (var singleRowValues in itemList.Value)
                // {
                Cell cell = new Cell();
                cell.DataType = CellValues.String;
                cell.CellValue = new CellValue(itemList[headerCell]); //
                newRow.AppendChild(cell);

                //}

            }
            sheetData.AppendChild(newRow);
        }

    //should I add here just this lines:
    //Columns columns = AutoSize(sheetData);
    //sheetPart.Worksheet.Append(columns);

    }
    return memoryStream.ToArray();

}

My insecurities:

  • Appending filter - I should know exact sequence spot where to put in, and I dont know how to calculate reference (for example A1: J100, but it wont be always that range, it should be somehow dynamically)
  • Auto width - I'm aware that I need to calculate each column width manually, but Im not sure where to add it...maybe at the end (view my comments in the code)

The links you have provided is outdated and would be applicable for older versions of .net framework.

  • To access SheetAutoFilter object use the Worksheet.AutoFilter property. The AutoFilterBase interface provides methods and properties to apply, clear or disable a filter and sort values in the filtered range. While calling the SheetAutoFilter.Apply method pass the CellRange object to enable filtering, reference link

    // Enable filtering for the specified cell range. CellRange range = sheet["A1:K9"]; sheet.AutoFilter.Apply(range);
  • For implementing code for auto width, reference link

    • include this chunk of code along with appending sheetdata
     //get your columns (where your width is set) Columns columns = AutoSize(sheetData); //add to a WorksheetPart.WorkSheet sheetPart.Worksheet = new Worksheet(); sheetPart.Worksheet.Append(columns); sheetPart.Worksheet.Append(sheetData);
    • you also need to include functions AutoSize and GetMaxCharacterWidth
     private Columns AutoSize(SheetData sheetData) { var maxColWidth = GetMaxCharacterWidth(sheetData); Columns columns = new Columns(); //this is the width of my font - yours may be different double maxWidth = 7; foreach (var item in maxColWidth) { //width = Truncate([{Number of Characters} * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256 double width = Math.Truncate((item.Value * maxWidth + 5) / maxWidth * 256) / 256; //pixels=Truncate(((256 * {width} + Truncate(128/{Maximum Digit Width}))/256)*{Maximum Digit Width}) double pixels = Math.Truncate(((256 * width + Math.Truncate(128 / maxWidth)) / 256) * maxWidth); //character width=Truncate(({pixels}-5)/{Maximum Digit Width} * 100+0.5)/100 double charWidth = Math.Truncate((pixels - 5) / maxWidth * 100 + 0.5) / 100; Column col = new Column() { BestFit = true, Min = (UInt32)(item.Key + 1), Max = (UInt32)(item.Key + 1), CustomWidth = true, Width = (DoubleValue)width }; columns.Append(col); } return columns; } private Dictionary<int, int> GetMaxCharacterWidth(SheetData sheetData) { //iterate over all cells getting a max char value for each column Dictionary<int, int> maxColWidth = new Dictionary<int, int>(); var rows = sheetData.Elements<Row>(); UInt32[] numberStyles = new UInt32[] { 5, 6, 7, 8 }; //styles that will add extra chars UInt32[] boldStyles = new UInt32[] { 1, 2, 3, 4, 6, 7, 8 }; //styles that will bold foreach (var r in rows) { var cells = r.Elements<Cell>().ToArray(); //using cell index as my column for (int i = 0; i < cells.Length; i++) { var cell = cells[i]; var cellValue = cell.CellValue == null ? string.Empty : cell.CellValue.InnerText; var cellTextLength = cellValue.Length; if (cell.StyleIndex != null && numberStyles.Contains(cell.StyleIndex)) { int thousandCount = (int)Math.Truncate((double)cellTextLength / 4); //add 3 for '.00' cellTextLength += (3 + thousandCount); } if (cell.StyleIndex != null && boldStyles.Contains(cell.StyleIndex)) { //add an extra char for bold - not 100% acurate but good enough for what i need. cellTextLength += 1; } if (maxColWidth.ContainsKey(i)) { var current = maxColWidth[i]; if (cellTextLength > current) { maxColWidth[i] = cellTextLength; } } else { maxColWidth.Add(i, cellTextLength); } } } return maxColWidth; }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM