How to merge Excel column with dynamic value - c#

I trying to merge the excel column when there is same value in the first 2 row. The value is coming from my database query. Currently what I had generated is like this:
I want to merge the column like this:
Here is my function code:
public static async Task<MemoryStream> getNewListingExcelWithContentColumnMerge<T>(List<T> list, List<string> header, string name, string headerTitle)
{
try
{
int row = 3;
int col = 1;
MemoryStream output = new MemoryStream();
using (ExcelPackage package = new ExcelPackage())
{
ExcelWorksheet ws = package.Workbook.Worksheets.Add(name);
ws.PrinterSettings.PaperSize = ePaperSize.A4;
ws.PrinterSettings.FitToPage = true;
ws.Cells["A1:D1"].Merge = true;
ws.Cells["A1:D1"].Value = headerTitle;
for (int i = 0; i < header.Count(); i++)
{
ws.Cells[row, col].Value = header[i];
col++;
}
ws.Cells[1, 1, 1, col].Style.Font.Bold = true;
col = 1;
row++;
for (int i = 0; i < list.Count(); i++)
{
Type type = list[i].GetType();
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
object asd = property.GetValue(list[i], null);
//Add data to the next line if consist of '\n'.
if (asd != null && asd.ToString().Contains(Environment.NewLine))
{
var splitValue = asd.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
var sameValuePlacementList = new List<int>();
for (var j = 0; j < splitValue.Count(); j++)
{
if (j == 0)
{
ws.Cells[row, col].Value = splitValue[j];
ws.Cells[row, col].Style.WrapText = true;
}
else
{
ws.Cells[row, col].RichText.Add(Environment.NewLine + splitValue[j]);
}
}
}
else
{
ws.Cells[row, col].Value = asd;
}
col++;
}
col = 1;
row++;
}
ws.Cells[3, 1, ws.Dimension.End.Row, ws.Dimension.End.Column - 1].AutoFitColumns();
ws.Cells[3, 1, ws.Dimension.End.Row, ws.Dimension.End.Column - 1].Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
ws.Cells[3, 1, ws.Dimension.End.Row, ws.Dimension.End.Column - 1].Style.Border.Top.Style = ExcelBorderStyle.Thin;
ws.Cells[3, 1, ws.Dimension.End.Row, ws.Dimension.End.Column - 1].Style.Border.Right.Style = ExcelBorderStyle.Thin;
ws.Cells[3, 1, ws.Dimension.End.Row, ws.Dimension.End.Column - 1].Style.Border.Left.Style = ExcelBorderStyle.Thin;
package.SaveAs(output);
return output;
}
}
catch (Exception ex)
{
return null;
}
}
What can I try next?

You can do it this way:
ws.Range[ws.Cells[1, 1], ws.Cells[4, 1]].Merge();
It will merge rows from 1 to 4 in column 1.

int tempRow = startRowForMerge;
int firstSameRowIndex = 0;
int lastSameRowIndex = 0;
int maxCount = tempRow + list.Count() - 1; // -1 because array start from 0
bool needToMerge = false;
foreach(int tempColumn in mergeColumnList)
{
tempRow = startRowForMerge;
for (int i = 0; i < list.Count(); i++)
{
if (tempRow < maxCount)
{
if (row > 4 && ws.Cells[tempRow, tempColumn].Value.ToString() == ws.Cells[tempRow - 1, tempColumn].Value.ToString())
{
needToMerge = true;
if (firstSameRowIndex == 0)
{
firstSameRowIndex = tempRow - 1;
}
lastSameRowIndex = tempRow;
}
else
{
if (needToMerge == true) // to merge data in between the list
{
ws.Cells[firstSameRowIndex, tempColumn, lastSameRowIndex, tempColumn].Merge = true;
ws.Cells[firstSameRowIndex, tempColumn, lastSameRowIndex, tempColumn].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
needToMerge = false;
firstSameRowIndex = 0;
lastSameRowIndex = 0;
}
}
}
else
{
if (needToMerge == true) // to merge data in last row
{
ws.Cells[firstSameRowIndex, tempColumn, lastSameRowIndex, tempColumn].Merge = true;
ws.Cells[firstSameRowIndex, tempColumn, lastSameRowIndex, tempColumn].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
needToMerge = false;
firstSameRowIndex = 0;
lastSameRowIndex = 0;
}
}
tempRow++;
}
}

Related

Multiplication and Sum in GridView ASP.Net C#

I have a datatable which is bound to GridView datasource as follows.
Overall i want to Multiply 'Quantity' column value with 'Part1 qty' column value until 'column5' cell value is repeating and so on
the result of operation should appear underneath the value as highlighted in red for understanding
My GridView data currently
I want the following output
Required Output
My GridMarkup
My GridMarkup
What I have done so far is
protected void GridView1_DataBound(object sender, EventArgs e)
{
int gridViewCellCount = GridView1.Rows[0].Cells.Count;
string[] columnNames = new string[gridViewCellCount];
for (int k = 0; k < gridViewCellCount; k++)
{
columnNames[k] = ((System.Web.UI.WebControls.DataControlFieldCell)(GridView1.Rows[0].Cells[k])).ContainingField.HeaderText;
}
for (int i = GridView1.Rows.Count - 1; i > 0; i--)
{
GridViewRow row = GridView1.Rows[i];
GridViewRow previousRow = GridView1.Rows[i - 1];
var result = Array.FindIndex(columnNames, element => element.EndsWith("QTY"));
var Arraymax=columnNames.Max();
int maxIndex = columnNames.ToList().IndexOf(Arraymax);
decimal MultiplicationResult=0;
int counter = 0;
for (int j = 8; j < row.Cells.Count; j++)
{
if (row.Cells[j].Text == previousRow.Cells[j].Text)
{
counter++;
if (row.Cells[j].Text != " " && result < maxIndex)
{
var Quantity = GridView1.Rows[i].Cells[1].Text;
var GLQuantity = GridView1.Rows[i].Cells[result].Text;
var PreviousQuantity= GridView1.Rows[i-1].Cells[1].Text;
var PreviousGLQuantity= GridView1.Rows[i-1].Cells[result].Text;
//var Quantity = dt.Rows[i].ItemArray[1];
//var GLQuantity = dt.Rows[i].ItemArray[Convert.ToInt64(result)].ToString();
var GLQ = GLQuantity.TrimEnd(new Char[] { '0' });
var PGLQ = PreviousGLQuantity.TrimEnd(new char[] { '0' });
if (GLQ == "")
{
GLQ = 0.ToString();
}
if (PGLQ == "")
{
PGLQ = 0.ToString();
}
MultiplicationResult = Convert.ToDecimal(Quantity) * Convert.ToDecimal(GLQ) + Convert.ToDecimal(PreviousQuantity) * Convert.ToDecimal(PGLQ);
object o = dt.Rows[i].ItemArray[j] + " " + MultiplicationResult.ToString();
GridView1.Rows[i].Cells[j].Text = o.ToString();
GridView1.Rows[i].Cells[j].Text.Replace("\n", "<br/>");
result++;
}
else
result++;
if (previousRow.Cells[j].RowSpan == 0)
{
if (row.Cells[j].RowSpan == 0)
{
previousRow.Cells[j].RowSpan += 2;
}
else
{
previousRow.Cells[j].RowSpan = row.Cells[j].RowSpan + 1;
}
row.Cells[j].Visible = false;
}
}
else
result++;
}
}
}
Thanks in advance.
We can use below Answer
protected void GridView1_DataBound(object sender, EventArgs e)
{
int gridViewCellCount = GridView1.Rows[0].Cells.Count;
string[] columnNames = new string[gridViewCellCount];
for (int k = 0; k < gridViewCellCount; k++)
{
columnNames[k] = ((System.Web.UI.WebControls.DataControlFieldCell)(GridView1.Rows[0].Cells[k])).ContainingField.HeaderText;
}
for (int i = GridView1.Rows.Count - 1; i > 0; i--)
{
GridViewRow row = GridView1.Rows[i];
GridViewRow previousRow = GridView1.Rows[i - 1];
var result = Array.FindIndex(columnNames, element => element.EndsWith("QTY"));
var Arraymax = columnNames.Max();
int maxIndex = columnNames.ToList().IndexOf(Arraymax);
decimal MultiplicationResult = 0;
decimal currentCellResult = 0;
for (int j = 8; j < row.Cells.Count; j++)
{
var defaultvalue = row.Cells[j].Text.ToString();
var defaultvalueArray = defaultvalue.Split(' ');
var originalMultiplicationResult = defaultvalueArray.Count() == 2 ? defaultvalueArray.Last() : "0";
var originalCellValue = defaultvalueArray.Count() == 2 ? defaultvalueArray.First() : row.Cells[j].Text.ToString();
if (originalCellValue == previousRow.Cells[j].Text)
{
if (row.Cells[j].Text != " " && result < maxIndex)
{
var Quantity = GridView1.Rows[i].Cells[1].Text;
var GLQuantity = GridView1.Rows[i].Cells[result].Text;
var PreviousQuantity = GridView1.Rows[i - 1].Cells[1].Text;
var PreviousGLQuantity = GridView1.Rows[i - 1].Cells[result].Text;
var GLQ = GLQuantity.TrimEnd(new Char[] { '0' });
var PGLQ = PreviousGLQuantity.TrimEnd(new char[] { '0' });
if (GLQ == "")
{
GLQ = 0.ToString();
}
if (PGLQ == "")
{
PGLQ = 0.ToString();
}
currentCellResult = Convert.ToDecimal(Quantity) * Convert.ToDecimal(GLQ);
MultiplicationResult = currentCellResult + Convert.ToDecimal(PreviousQuantity) * Convert.ToDecimal(PGLQ);
if (row.Cells[j].RowSpan == 0)
{
//DataTable dt = (DataTable)ViewState["dt"];
object o = dt.Rows[i].ItemArray[j] + " " + MultiplicationResult.ToString();
previousRow.Cells[j].Text = o.ToString();
//previousRow.Cells[j].Text = previousRow.Cells[j].Text.Split("");
}
else
{
//DataTable dt = (DataTable)ViewState["dt"];
var t = Convert.ToDecimal(originalMultiplicationResult) - Convert.ToDecimal(currentCellResult) + MultiplicationResult;
object o = dt.Rows[i].ItemArray[j] + " " + t.ToString();
previousRow.Cells[j].Text = o.ToString();
//previousRow.Cells[j].Text.Replace("\n", "<br>");
}
result++;
}
else
result++;
if (previousRow.Cells[j].RowSpan == 0)
{
if (row.Cells[j].RowSpan == 0)
{
previousRow.Cells[j].RowSpan += 2;
}
else
{
previousRow.Cells[j].RowSpan = row.Cells[j].RowSpan + 1;
}
row.Cells[j].Visible = false;
}
}
else
result++;
}
}
}

C# WPF DataTable move empty cells to left

I have a DataTable and i would like to loop through the cells in a row and to move empty cells to the left, so that the cells with data in are in the columns to the right and the empty to the left.
This is because i am getting the cell before i do all of this and split it on a comma, and place the second section of the split into the cell to the right of that cell
So if i have a blank cell there, which there will be after the code, it will fill into a blank cell rather than a cell with data in
I have this code currently that doesn't seem to fully work
int rowcount = 0;
numberoftruncationsneeded = 0;
foreach (DataRow row in dt.Rows)
{
int columncount = 0;
foreach (var col in row.ItemArray)
{
if (dt.Columns[columncount].Caption.Contains("Address"))
{
if (dt.Columns.Count > columncount + 1)
{
if (dt.Columns[columncount + 1].Caption.Contains("Address"))
{
if (dt.Rows[rowcount].ItemArray[columncount].ToString().Length >= 32)
{
bool isblank = false;
int blankrow = 0;
foreach (DataColumn colzer in dt.Columns)
{
if (colzer.Caption.Contains("Address") && (dt.Columns.IndexOf(colzer) >= columncount))
{
if (dt.Rows[rowcount].ItemArray[dt.Columns.IndexOf(colzer)].ToString().Trim() == "")
{
dt.Rows[rowcount][dt.Columns.IndexOf(colzer)] = dt.Rows[rowcount][dt.Columns.IndexOf(colzer) - 1].ToString();
dt.Rows[rowcount][dt.Columns.IndexOf(colzer) - 1] = "";
}
}
}
bool isbad = true;
if (isPostCode(dt.Rows[rowcount][columncount + 1].ToString()))
isbad = false;
string firstaddress = "";
string secondaddress = " ";
while (isbad == true)
{
if (firstaddress == "")
firstaddress = dt.Rows[rowcount].ItemArray[columncount].ToString();
if (!firstaddress.Contains(",") || firstaddress == "")
{
isbad = false;
break;
}
int lastspace = firstaddress.LastIndexOf(",");
var tempsecond = firstaddress.Remove(0, lastspace + 1);
firstaddress = firstaddress.Substring(0, lastspace);
secondaddress = tempsecond + " " + secondaddress;
if (firstaddress.Length < 32)
isbad = false;
}
dt.Rows[rowcount][columncount] = firstaddress;
if (firstaddress.Length >= 32)
numberoftruncationsneeded++;
var temp = dt.Rows[rowcount][columncount + 1];
dt.Rows[rowcount][columncount + 1] = secondaddress + "" + temp;
}
}
}
}
columncount++;
}
rowcount++;
}
My issue was with the column loop.
Id find a blank and move it one to the left, but then the program doesnt know its meant to move it further left
To combat this i am looping backwards rather than forwards to do this
if(dt.Rows[rowcount].ItemArray[columncount].ToString().Contains(","))
{
for (int i = dt.Columns.Count - 1; i > columncount + 1; i--)
{
if (dt.Columns[i].Caption.Contains("Address"))
{
if (dt.Rows[rowcount].ItemArray[i].ToString().Trim() == "")
{
dt.Rows[rowcount][i] = dt.Rows[rowcount][i - 1].ToString();
dt.Rows[rowcount][i - 1] = "";
}
}
}
}
//foreach (DataColumn colzer in dt.Columns)
//{
// if (colzer.Caption.Contains("Address") && (dt.Columns.IndexOf(colzer) >= columncount))
// {
// if (dt.Rows[rowcount].ItemArray[dt.Columns.IndexOf(colzer)].ToString().Trim() == "")
// {
// dt.Rows[rowcount][dt.Columns.IndexOf(colzer)] = dt.Rows[rowcount][dt.Columns.IndexOf(colzer) - 1].ToString();
// dt.Rows[rowcount][dt.Columns.IndexOf(colzer) - 1] = "";
// }
// }
//}

Dates being flipped through inter op excel

I am having a strange issue with dates in excel at present some dates when exported from my grid while displaying file are swapping the month and days however I used the number format to account for this but still some items seems to have an issue.
private static void ExportToExcel(List<ListViewItem> items, ListView listView)
{
using (var progressIndicatorForm = new ProgressIndicatorForm(0, items.Count))
{
try
{
progressIndicatorForm.Show();
System.Windows.Forms.Application.DoEvents();
Microsoft.Office.Interop.Excel.Application app = null;
Microsoft.Office.Interop.Excel.Workbook workBook = null;
Microsoft.Office.Interop.Excel.Worksheet workSheet = null;
try
{
app = new Microsoft.Office.Interop.Excel.Application();
workBook = app.Workbooks.Add(1);
workSheet = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Worksheets[1];
List<string> columnNames = GetColumnNames(listView);
for (int columnIndex = 0; columnIndex < columnNames.Count; columnIndex++)
{
workSheet.Cells[0 + 1, columnIndex + 1] = columnNames[columnIndex];
}
for (int rowIndex = 1; rowIndex <= items.Count; rowIndex++)
{
progressIndicatorForm.Current = rowIndex;
progressIndicatorForm.Description = string.Format("Exporting {0} of {1} records...", rowIndex, items.Count);
System.Windows.Forms.Application.DoEvents();
var item = items[rowIndex - 1];
for (var columnIndex = 0; columnIndex < listView.Columns.Count; columnIndex++)
{
var column = listView.Columns[columnIndex];
if (column.Tag != null && column.Tag.ToString() == typeof(DateTime).ToString())
{
string text = item.SubItems[columnIndex].Text;
DateTime? dateTime = ParseDateTime(text);
if (dateTime.HasValue)
{
Range range = (Range)workSheet.Cells[rowIndex + 1, columnIndex + 1];
range.Value = dateTime.Value.ToOADate();
range.NumberFormat = "dd/MM/yyyy";
}
else
{
workSheet.Cells[rowIndex + 1, columnIndex + 1] = text;
}
}
else
{
workSheet.Cells[rowIndex + 1, columnIndex + 1] = item.SubItems[columnIndex].Text;
}
}
}
app.Visible = true;
}
catch (Exception ex)
{
ExceptionManager.HandleUnexpectedException(ex);
}
finally
{
app = null;
workBook = null;
workSheet = null;
}
}
catch (Exception ex)
{
ExceptionManager.HandleUnexpectedException(ex);
}
finally
{
progressIndicatorForm.Close();
}
}
}
As you see I am using the following which is the suggested method for the dd/mm/yyyy
range.NumberFormat = "dd/MM/yyyy";

Collapsing the space between bars on a StackedBar100 in MSChart

Essentially I have to show rows of bars on a stacked bar chart. There will be one for each question. Optionally there will be an extra bar or two for each question if there's a National score or a Competitor score is available.
My issue is one of presentation. I wish to place the bars central relative to the label for the question or remove gaps if one of the national or competitor scores isn't present.
Perhaps a picture will help:
I put together an example quickly (that generated the above picture) into an MVC project. These are the files:
Index.cshtml
<h2>Attempt 2</h2>
<img src="/Home/StackedBar100" />
<h2>Attempt 1</h2>
<img src="/Home/StackedBar100_FirstAttempt" />
HomeController.cs
<!-- language: c# -->
public class HomeController : Controller
{
List<Color> colors = new List<Color>();
string[] rows = new string[] { "Q1", "Q2", "Q3", "Q4" };
string[] stackTypes = new string[] { "National", "Value", "Competitor" };
Color[] stackColors = new Color[] { Color.White, Color.Green, Color.Orange };
protected override void Initialize(RequestContext requestContext)
{
// Set up bands of colours for testing purposes.
int diff = (255 - 20) / 10;
for (int c = 10; c > 0; c--)
{
colors.Add(Color.FromArgb(0, (c * diff) + 10, 0));
}
base.Initialize(requestContext);
}
public ActionResult Index()
{
return View();
}
public ActionResult StackedBar100()
{
var chart = new Chart();
var chartArea = new ChartArea("Default");
chart.ChartAreas.Add(chartArea);
chart.Width = 640;
chart.Height = 480;
var r = new Random();
for (int s = 0; s < stackTypes.Count(); s++)
{
var stack = stackTypes[s];
var stackColor = stackColors[s];
{
for (int i = 1; i <= 10; i++)
{
var series = new Series(stack + i.ToString());
series.ChartType = SeriesChartType.StackedBar100;
series.Color = colors[i - 1];
series.BorderColor = stackColor;
series["StackedGroupName"] = stack;
series["DrawSideBySide"] = "true";
series.IsValueShownAsLabel = true;
series.LabelForeColor = Color.White;
chart.Series.Add(series);
}
}
}
var dt = CreateData();
foreach (DataRow row in dt.Rows)
{
var question = row["Question"];
var stack = row["Stack"];
var hidden = Convert.ToBoolean(row["Hidden"]);
var ks = "";
for (int k = 1; k <= 10; k++)
{
ks = k.ToString();
chart.Series[stack + ks].Points.AddXY(question, row[ks]);
if (hidden)
{
chart.Series[stack + ks].Points.Last().IsEmpty = true;
}
else if ((row[ks] as double?) < 3)
{
chart.Series[stack + ks].Points.Last().IsValueShownAsLabel = false;
}
}
}
return ReturnChartAsImage(chart);
}
private DataTable CreateData()
{
var r = new Random();
var dt = new DataTable("Chart Data");
dt.Columns.Add("Question", typeof(string));
dt.Columns.Add("Stack", typeof(string));
dt.Columns.Add("Hidden", typeof(string));
for (int i = 1; i <= 10; i++)
{
dt.Columns.Add(i.ToString(), typeof(double));
}
foreach (var row in rows.OrderByDescending(rw => rw))
{
foreach (var stack in stackTypes)
{
if (
(stack == "Value") && row != "Q4" ||
(stack == "National" && (row == "Q2" || row == "Q4")) ||
(stack == "Competitor" && (row == "Q3" || row == "Q4")))
{
var dr = dt.NewRow();
dr["Question"] = row;
dr["Hidden"] = false;
dr["Stack"] = stack;
for (int k = 1; k <= 10; k++)
{
dr[k.ToString()] = r.NextDouble() * 10;
}
dt.Rows.Add(dr);
}
else
{
var dr = dt.NewRow();
dr["Question"] = row;
dr["Stack"] = stack;
dr["Hidden"] = true;
dt.Rows.Add(dr);
}
}
}
dt.WriteXml(#"c:\Users\chris_000\Desktop\1.xml");
return dt;
}
public ActionResult StackedBar100_FirstAttempt()
{
var chart = new Chart();
var chartArea = new ChartArea("Default");
chart.ChartAreas.Add(chartArea);
chart.Width = 640;
chart.Height = 480;
for (int i = 1; i <= 30; i++)
{
var series = new Series("Series" + i.ToString());
series.ChartType = SeriesChartType.StackedBar100;
series.Color = colors[(i - 1) % 10];
if (i <= 10)
{
series["StackedGroupName"] = "Value";
}
else if (i > 10 && i <= 20)
{
series["StackedGroupName"] = "National";
series.BorderColor = Color.Green;
}
else
{
series["StackedGroupName"] = "Competitor";
series.BorderColor = Color.Orange;
}
chart.Series.Add(series);
}
var dt = CreateData_FirstAttempt();
foreach (DataRow row in dt.Rows)
{
var question = row["Question"];
var group = row["Stack"];
for (int k = 1; k <= 30; k++)
{
chart.Series["Series" + k.ToString()].Points.AddXY(question, row[k.ToString()]);
}
}
return ReturnChartAsImage(chart);
}
private DataTable CreateData_FirstAttempt()
{
var r = new Random();
var dt = new DataTable("Chart Data");
dt.Columns.Add("Question", typeof(string));
dt.Columns.Add("Stack", typeof(string)); // Value, National, Competitor
for (int i = 1; i <= 30; i++)
{
dt.Columns.Add(i.ToString(), typeof(double));
}
foreach (var row in rows.OrderByDescending(rw => rw))
{
var dr = dt.NewRow();
dr["Question"] = row;
dr["Stack"] = "Score";
for (int k = 1; k <= 30; k++)
{
if (k <= 10)
{
if (row != "Q4")
{
dr[k.ToString()] = r.NextDouble() * 100;
}
else
{
dr[k.ToString()] = DBNull.Value;
}
}
else if (k > 10 && k <= 20)
{
if (row == "Q2" || row == "Q4")
{
dr[k.ToString()] = r.NextDouble();
}
else
{
dr[k.ToString()] = DBNull.Value;
}
}
else
{
if (row == "Q3" || row == "Q4")
{
dr[k.ToString()] = r.NextDouble();
}
else
{
dr[k.ToString()] = DBNull.Value;
}
}
}
dt.Rows.Add(dr);
}
return dt;
}
private ActionResult ReturnChartAsImage(Chart chart)
{
MemoryStream ms = new MemoryStream();
chart.SaveImage(ms, ChartImageFormat.Png);
return File(ms.ToArray(), "image/png");
}
}
That's a long example, but shows two different attempts at building multiple bars on a stacked chart. One using 30 columns, but splitting every 10 for each group. The second (more sensible) naming the stacks after the Value, National or Competitor they're supposed to represent.
So, in short, can I collapse the space occupied but the missing series/bars? Is it the way I'm feeding the data in perhaps?
Thanks.

Merge cells using EPPlus?

I'm using the EPPlus library to read/write Excel files: http://epplus.codeplex.com/
I'm trying to simply merge some cells when writing a document:
using (ExcelPackage pck = new ExcelPackage())
{
//Create the worksheet
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Demo");
//Format the header for column 1-3
using (ExcelRange rng = ws.Cells["A1:C1"])
{
bool merge = rng.Merge;
}
}
There's a property named Merge that simply returns true or false. I thought maybe that would Merge the cells, but it doesn't.
Anyone know how to do this?
You have to use it like this:
ws.Cells["A1:C1"].Merge = true;
instead of:
using (ExcelRange rng = ws.Cells["A1:C1"])
{
bool merge = rng.Merge;
}
If you want to merge cells dynamically, you can also use:
worksheet.Cells[FromRow, FromColumn, ToRow, ToColumn].Merge = true;
All these variables are integers.
You can create a extension method:
public static void Merge(this ExcelRangeBase range)
{
ExcelCellAddress start = range.Start;
ExcelCellAddress end = range.End;
range.Worksheet.Cells[start.Row, start.Column, end.Row, end.Column].Merge = true;
}
You can use this as you would via interop:
range.Merge();
int inicio = CELDA_CUERPO;
bool values = true;
int COLUMNA_A = 0;
int finx_a = 0;
int finy_a = 0;
int COLUMNA_B = 1;
int finx_b = 0;
int finy_b = 0;
//Pintar cabecera:
for (int i = 0; i < ListaCabecera.Length; i++)
{
celda = $"{letras[i]}{CELDA_CABECERA}";
if (i == 0)
{
inicioRango = celda;
}
Sheet.Cells[celda].Value = ListaCabecera[i];
//System.Drawing.Color colFromHex = System.Drawing.ColorTranslator.FromHtml("#B7DEE8");
Sheet.Cells[celda].Style.Font.Color.SetColor(Color.FromArgb(0, 124, 183));
Sheet.Cells[celda].Style.Fill.PatternType = ExcelFillStyle.Solid;
Sheet.Cells[celda].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(232, 235, 249));
Sheet.Cells[celda].Style.Font.Bold = true;
Sheet.Cells[celda].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
}
//Pintar detalle:
for (int i = 0; i < Datos.GetLength(0); i++)
{
for (int j = 0; j < Datos.GetLength(1); j++)
{
celda = $"{letras[j]}{CELDA_CUERPO + i}";
finalizaRango = celda;
if (j < 3) if (Datos[i, j].valor != null && Datos[i, j + 1].valor == null)
{
Sheet.Cells[celda].Style.Font.Color.SetColor(Color.FromArgb(156, 0, 6));
Sheet.Cells[celda].Style.Fill.PatternType = ExcelFillStyle.Solid;
Sheet.Cells[celda].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(255, 199,206));
}
Sheet.Cells[celda].Value = Datos[i, j].valor;
}
//::::::::::::::::::: MERGE A ::::::::::::::::::::
if (i < Datos.GetLength(0) - 1)
{
// :::::::::::::::::::::: x :::::::::::::::::::::::::::::::::
if (values)
{
if (Datos[i, COLUMNA_A].valor == Datos[i, COLUMNA_A].valor)
{
values = false;
finx_a = inicio + i;
finx_b = inicio + i;
//list_x.Add(finx_b);
}
}
else
{
if (Datos[i - 1, COLUMNA_A].valor != Datos[i, COLUMNA_A].valor)
{
finx_a = inicio + i;
}
if (Datos[i - 1, COLUMNA_B].valor != Datos[i, COLUMNA_B].valor)
{
finx_b = inicio + i;
//list_x.Add(finx_b);
}
}
// :::::::::::::::::::::: y (A) :::::::::::::::::::::::::::::::::
if (Datos[i, COLUMNA_A].valor != Datos[i + 1, COLUMNA_A].valor)
{
finy_a = inicio + i;
//list_y.Add(finy);
Sheet.Cells[$"A{finx_a}:A{finy_a}"].Value = Datos[i, COLUMNA_A].valor;
Sheet.Cells[$"A{finx_a}:A{finy_a}"].Merge = true;
Sheet.Cells[$"A{finx_a}:A{finy_a}"].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
}
// :::::::::::::::::::::: y (B) :::::::::::::::::::::::::::::::::
if (Datos[i, COLUMNA_B].valor != Datos[i + 1, COLUMNA_B].valor)
{
finy_b = inicio + i;
//list_y.Add(finy_b);
Sheet.Cells[$"B{finx_b}:B{finy_b}"].Value = Datos[i, COLUMNA_B].valor;
Sheet.Cells[$"B{finx_b}:B{finy_b}"].Merge = true;
Sheet.Cells[$"B{finx_b}:B{finy_b}"].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
}

Categories