6
votes

what i need is group rows when the value of the row is the same as the previous row, the value of "B3" is the same of "B2", like this:

enter image description here

i´m usin c# with epplus, and i see how can i do something similar to this with the outline option, and is similar to what i want, but this option have some disadvantages, such as that which doesn´t automatically group based on values and can´t do various groups....

is it possible to do this with EPPLUS? if it´s not posible, how can i add the vba code to c#?, i try this:

  StringBuilder vbaCode = new StringBuilder();

  vbaCode.AppendLine("Sheets('Sheet1').Activate");
  vbaCode.AppendLine("Range('A1: D11').Select");
  vbaCode.AppendLine("Selection.Subtotal GroupBy:= 1, Function:= xlSum, TotalList:= Array(2, 3),Replace:= True, PageBreaks:= False, SummaryBelowData:= True");
pck.Save();

but not work, i can´t open the Excel file.

EDIT

With sugested now i try Interop with the group function, but for a extrain reason he is grouping columns not rows, this is the code:

 var ExApp = new Microsoft.Office.Interop.Excel.Application();
 Microsoft.Office.Interop.Excel.Workbooks Wbs = ExApp.Workbooks;
 Microsoft.Office.Interop.Excel.Workbook Wb = Wbs.Open(fi.FullName.ToString());
 Microsoft.Office.Interop.Excel.Sheets wss = Wb.Worksheets;
 Microsoft.Office.Interop.Excel.Worksheet Ws = (Microsoft.Office.Interop.Excel.Worksheet)wss.get_Item("Sheet1");
 Ws.Range["A6:A10"].Group();
 Ws.Outline.SummaryRow =Microsoft.Office.Interop.Excel.XlSummaryRow.xlSummaryAbove;
 ExApp.Visible = true;
2
EPPlus can't do something that isn't possible with Excel. If you can do something with Excel or VBA though, you can do it with EPPlus. You don't need VBA to group rows, you can just write the same logic in C# - eg sheet.Cells["A1:D11"] will return an ExcelRange on which you can call Group - Panagiotis Kanavos
yes, is supossed that all that yo can do with Excel yo ca do with EEPLUS, but i can,t see how to do this, in Excel this option is in the Data tab, subtotal option. If yo know how to do it this with EPPLUS please put a simple example of how this work. when i put **sheet.Cells["A1:D11"] ** dont see the group option, i can see that exist one named group by, but not understand how it Works. - Ion

2 Answers

10
votes

I see this is already answered but figured I would provide an EPPlus way which you can certainly do but you do need to manually create the sum cells:

[TestMethod]
public void Row_Grouping_Test()
{
    //http://stackoverflow.com/questions/41636336/grouping-excel-rows-with-epplus

    //Throw in some data
    var datatable = new DataTable("tblData");
    datatable.Columns.AddRange(new[]
    {
        new DataColumn("Header", typeof (string)), 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] = $"Header {i}"; row[1] = i; row[2] = i * 10; row[3] = Path.GetRandomFileName(); datatable.Rows.Add(row);
    }

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

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

        worksheet.Cells["A11"].Value = "TOTAL";
        worksheet.Cells["B11"].Formula = "SUBTOTAL(9,B2:B10)";
        worksheet.Cells["C11"].Formula = "SUBTOTAL(9,C2:C10)";
        worksheet.Row(11).Style.Font.Bold = true;

        //Row Group 1 (start with 1 since row index is 1-based)
        for (var i = 1; i <= datatable.Rows.Count; i++)
            worksheet.Row(i).OutlineLevel = 1;

        pck.Save();
    }
}

Which looks like this:

enter image description here

0
votes

I am not familiar with EPPLUS libary.
but you can achieve that task very easily using Microsoft.Office.Interop.Excel namespace.
and than you can do it like you do it using Vba- (using the Merge() method) note that you will need to add a reference of that namespace to your project.
here is an example:

using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;

namespace WindowsFormsApplication32
{
    public partial class Form1 : Form
    {
        public Microsoft.Office.Interop.Excel.Application ExApp;


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            ExApp = new Microsoft.Office.Interop.Excel.Application();
            // CREATE A NEW WORKBOOK (you can also open existing workbook using the Open() method)
            Microsoft.Office.Interop.Excel.Workbook Wb = ExApp.Workbooks.Add();
            // SET WORKSHEET
            Microsoft.Office.Interop.Excel.Worksheet Ws = Wb.Worksheets.Add();
            // MERGE CELLS (the answer to your question)
            Ws.Range["A1:G5"].Merge();
            // GROUP ROWS (the final answer to your question)
            Ws.Rows["4:7"].Group();
            ExApp.Visible = true;
        }
    }
}