Initial commit of the ClosedXML library

Establishes the foundational structure, core Excel functionality, and tooling.

- Implements base components for cells, ranges, columns, and rows.
- Integrates a custom calculation engine with a wide range of Excel functions.
- Adds comprehensive support for styling, conditional formatting, data validation, comments, pictures, and charts.
- Configures build setup, project metadata (NuGet), and developer guidelines.
- Includes editor and Git attributes for consistent code style and line endings.
This commit is contained in:
Thom Lamb
2026-06-23 11:02:53 -05:00
parent 28bc05cf54
commit 2cd6df6481
1092 changed files with 97270 additions and 408 deletions
+51
View File
@@ -0,0 +1,51 @@
using ClosedXML.Excel;
using System;
using System.Data;
using System.Linq;
namespace ClosedXML_Examples.Misc
{
public class AddingDataSet : IXLExample
{
public void Create(String filePath)
{
var wb = new XLWorkbook();
var dataSet = GetDataSet();
// Add all DataTables in the DataSet as a worksheets
wb.Worksheets.Add(dataSet);
foreach (var ws in wb.Worksheets)
ws.Columns().AdjustToContents();
wb.SaveAs(filePath);
}
private DataSet GetDataSet()
{
var ds = new DataSet();
ds.Tables.Add(GetTable("Patients"));
ds.Tables.Add(GetTable("Employees"));
ds.Tables.Add(GetTable("Information"));
return ds;
}
private DataTable GetTable(String tableName)
{
DataTable table = new DataTable();
table.TableName = tableName;
table.Columns.Add("Dosage", typeof(int));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Rows.Add(25, "Indocin", "David", new DateTime(2000, 1, 1));
table.Rows.Add(50, "Enebrel", "Sam", new DateTime(2000, 1, 2));
table.Rows.Add(10, "Hydralazine", "Christoff", new DateTime(2000, 1, 3));
table.Rows.Add(21, "Combivent", "Janet", new DateTime(2000, 1, 4));
table.Rows.Add(100, "Dilantin", "Melanie", new DateTime(2000, 1, 5));
return table;
}
}
}
@@ -0,0 +1,79 @@
using System;
using System.Data;
using System.Linq;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class AddingDataTableAsWorksheet : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var dataTable = GetTable("Information");
// Add a DataTable as a worksheet
wb.Worksheets.Add(dataTable);
wb.Worksheets.First().Columns().AdjustToContents();
wb.SaveAs(filePath);
}
// Private
private DataTable GetTable(String tableName)
{
DataTable table = new DataTable();
table.TableName = tableName;
table.Columns.Add("Dosage", typeof(int));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Rows.Add(25, "Indocin", "David", new DateTime(2000, 1, 1));
table.Rows.Add(50, "Enebrel", "Sam", new DateTime(2000, 1, 2));
table.Rows.Add(10, "Hydralazine", "Christoff", new DateTime(2000, 1, 3));
table.Rows.Add(21, "Combivent", "Janet", new DateTime(2000, 1, 4));
table.Rows.Add(100, "Dilantin", "Melanie", new DateTime(2000, 1, 5));
return table;
}
// Override
#endregion
}
}
+113
View File
@@ -0,0 +1,113 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class AdjustToContents : IXLExample
{
// Public
public void Create(String filePath)
{
using (var wb = new XLWorkbook())
{
var ws = wb.Worksheets.Add("Adjust To Contents");
// Set some values with different font sizes
ws.Cell(1, 1).Value = "Tall Row";
ws.Cell(1, 1).Style.Font.FontSize = 30;
ws.Cell(2, 1).Value = "Very Wide Column";
ws.Cell(2, 1).Style.Font.FontSize = 20;
// Adjust column width
ws.Column(1).AdjustToContents();
// Adjust row heights
ws.Rows(1, 2).AdjustToContents();
// You can also adjust all rows/columns in one shot
// ws.Rows().AdjustToContents();
// ws.Columns().AdjustToContents();
// We'll now select which cells should be used for calculating the
// column widths (same method applies for row heights)
// Set the values
ws.Cell(4, 2).Value = "Width ignored because calling column.AdjustToContents(5, 7)";
ws.Cell(5, 2).Value = "Short text";
ws.Cell(6, 2).Value = "Width ignored because it's part of a merge";
ws.Range(6, 2, 6, 4).Merge();
ws.Cell(7, 2).Value = "Width should adjust to this cell";
ws.Cell(8, 2).Value = "Width ignored because calling column.AdjustToContents(5, 7)";
// Adjust column widths only taking into account rows 5-7
// (merged cells will be ignored)
ws.Column(2).AdjustToContents(5, 7);
// You can also specify the starting row to start calculating the widths:
// e.g. ws.Column(3).AdjustToContents(9);
var ws2 = wb.Worksheets.Add("Adjust Widths");
ws2.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255;
for (Int32 co = 0; co < 90; co += 5)
{
ws2.Cell(1, (co / 5) + 2).SetValue("Text to adjust - " + co).Style.Alignment.TextRotation = co;
}
ws2.Columns().AdjustToContents();
var ws4 = wb.Worksheets.Add("Adjust Widths 2");
ws4.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255;
for (Int32 co = 0; co < 90; co += 5)
{
var c = ws4.Cell(1, (co / 5) + 2);
c.RichText.AddText("Text to adjust - " + co).SetBold();
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("World!").SetBold().SetFontColor(XLColor.Blue).SetFontSize(25);
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("Hello Cruel and unsusual world").SetBold().SetFontSize(20);
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("Hello").SetBold();
c.Style.Alignment.SetTextRotation(co);
}
ws4.Columns().AdjustToContents();
var ws3 = wb.Worksheets.Add("Adjust Heights");
ws3.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255;
for (Int32 ro = 0; ro < 90; ro += 5)
{
ws3.Cell((ro / 5) + 2, 1).SetValue("Text to adjust - " + ro).Style.Alignment.TextRotation = ro;
}
ws3.Rows().AdjustToContents();
var ws5 = wb.Worksheets.Add("Adjust Heights 2");
ws5.Cell(1, 1).SetValue("Text to adjust - 255").Style.Alignment.TextRotation = 255;
for (Int32 ro = 0; ro < 90; ro += 5)
{
var c = ws5.Cell((ro / 5) + 2, 1);
c.RichText.AddText("Text to adjust - " + ro).SetBold();
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("World!").SetBold().SetFontColor(XLColor.Blue).SetFontSize(10);
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("Hello Cruel and unsusual world").SetBold().SetFontSize(15);
c.RichText.AddText(Environment.NewLine);
c.RichText.AddText("Hello").SetBold();
c.Style.Alignment.SetTextRotation(ro);
}
ws5.Rows().AdjustToContents();
var ws6 = wb.Worksheets.Add("Absurdly wide column");
ws6.Cell("A1").Value = "Some string";
// This column's width should be capped at 255
ws6.Cell("B1").Value = @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
ws6.Columns().AdjustToContents();
wb.SaveAs(filePath, true);
}
}
}
}
@@ -0,0 +1,25 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class AdjustToContentsWithAutoFilter : IXLExample
{
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("AutoFilter");
ws.Cell("A1").Value = "AVeryLongColumnHeader";
ws.Cell("A2").Value = "John";
ws.Cell("A3").Value = "Hank";
ws.Cell("A4").Value = "Dagny";
ws.RangeUsed().SetAutoFilter();
ws.Columns().AdjustToContents();
wb.SaveAs(filePath);
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class AutoFilter : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("AutoFilter");
ws.Cell("A1").Value = "Names";
ws.Cell("A2").Value = "John";
ws.Cell("A3").Value = "Hank";
ws.Cell("A4").Value = "Dagny";
ws.RangeUsed().SetAutoFilter();
// Your can turn off the autofilter by:
// 1) worksheet.AutoFilter.Clear()
// 2) worksheet.SetAutoFilter(false)
// 3) Pick any range in the worksheet and call the above methods on the range
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+59
View File
@@ -0,0 +1,59 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class BlankCells : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Sheet1");
ws.Cell(1, 1).Value = "X";
ws.Cell(1, 1).Clear();
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+148
View File
@@ -0,0 +1,148 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class CellValues : IXLExample
{
public void Create(String filePath)
{
using (var workbook = new XLWorkbook())
{
var ws = workbook.Worksheets.Add("Cell Values");
// Set the titles
ws.Cell(2, 2).Value = "Initial Value";
ws.Cell(2, 3).Value = "Casting";
ws.Cell(2, 4).Value = "Using Get...()";
ws.Cell(2, 5).Value = "Using GetValue<T>()";
ws.Cell(2, 6).Value = "GetString()";
ws.Cell(2, 7).Value = "GetFormattedString()";
//////////////////////////////////////////////////////////////////
// DateTime
// Fill a cell with a date
var cellDateTime = ws.Cell(3, 2);
cellDateTime.Value = new DateTime(2010, 9, 2);
cellDateTime.Style.DateFormat.Format = "yyyy-MMM-dd";
// Extract the date in different ways
DateTime dateTime1 = (DateTime)cellDateTime.Value;
DateTime dateTime2 = cellDateTime.GetDateTime();
DateTime dateTime3 = cellDateTime.GetValue<DateTime>();
String dateTimeString = cellDateTime.GetString();
String dateTimeFormattedString = cellDateTime.GetFormattedString();
// Set the values back to cells
// The apostrophe is to force ClosedXML to treat the date as a string
ws.Cell(3, 3).Value = dateTime1;
ws.Cell(3, 4).Value = dateTime2;
ws.Cell(3, 5).Value = dateTime3;
ws.Cell(3, 6).Value = "'" + dateTimeString;
ws.Cell(3, 7).Value = "'" + dateTimeFormattedString;
//////////////////////////////////////////////////////////////////
// Boolean
// Fill a cell with a boolean
var cellBoolean = ws.Cell(4, 2);
cellBoolean.Value = true;
// Extract the boolean in different ways
Boolean boolean1 = (Boolean)cellBoolean.Value;
Boolean boolean2 = cellBoolean.GetBoolean();
Boolean boolean3 = cellBoolean.GetValue<Boolean>();
String booleanString = cellBoolean.GetString();
String booleanFormattedString = cellBoolean.GetFormattedString();
// Set the values back to cells
// The apostrophe is to force ClosedXML to treat the boolean as a string
ws.Cell(4, 3).Value = boolean1;
ws.Cell(4, 4).Value = boolean2;
ws.Cell(4, 5).Value = boolean3;
ws.Cell(4, 6).Value = "'" + booleanString;
ws.Cell(4, 7).Value = "'" + booleanFormattedString;
//////////////////////////////////////////////////////////////////
// Double
// Fill a cell with a double
var cellDouble = ws.Cell(5, 2);
cellDouble.Value = 1234.567;
cellDouble.Style.NumberFormat.Format = "#,##0.00";
// Extract the double in different ways
Double double1 = (Double)cellDouble.Value;
Double double2 = cellDouble.GetDouble();
Double double3 = cellDouble.GetValue<Double>();
String doubleString = cellDouble.GetString();
String doubleFormattedString = cellDouble.GetFormattedString();
// Set the values back to cells
// The apostrophe is to force ClosedXML to treat the double as a string
ws.Cell(5, 3).Value = double1;
ws.Cell(5, 4).Value = double2;
ws.Cell(5, 5).Value = double3;
ws.Cell(5, 6).Value = "'" + doubleString;
ws.Cell(5, 7).Value = "'" + doubleFormattedString;
//////////////////////////////////////////////////////////////////
// String
// Fill a cell with a string
var cellString = ws.Cell(6, 2);
cellString.Value = "Test Case";
// Extract the string in different ways
String string1 = (String)cellString.Value;
String string2 = cellString.GetString();
String string3 = cellString.GetValue<String>();
String stringString = cellString.GetString();
String stringFormattedString = cellString.GetFormattedString();
// Set the values back to cells
ws.Cell(6, 3).Value = string1;
ws.Cell(6, 4).Value = string2;
ws.Cell(6, 5).Value = string3;
ws.Cell(6, 6).Value = stringString;
ws.Cell(6, 7).Value = stringFormattedString;
//////////////////////////////////////////////////////////////////
// TimeSpan
// Fill a cell with a timeSpan
var cellTimeSpan = ws.Cell(7, 2);
cellTimeSpan.Value = new TimeSpan(1, 2, 31, 45);
// Extract the timeSpan in different ways
TimeSpan timeSpan1 = (TimeSpan)cellTimeSpan.Value;
TimeSpan timeSpan2 = cellTimeSpan.GetTimeSpan();
TimeSpan timeSpan3 = cellTimeSpan.GetValue<TimeSpan>();
String timeSpanString = "'" + cellTimeSpan.GetString();
String timeSpanFormattedString = "'" + cellTimeSpan.GetFormattedString();
// Set the values back to cells
ws.Cell(7, 3).Value = timeSpan1;
ws.Cell(7, 4).Value = timeSpan2;
ws.Cell(7, 5).Value = timeSpan3;
ws.Cell(7, 6).Value = timeSpanString;
ws.Cell(7, 7).Value = timeSpanFormattedString;
//////////////////////////////////////////////////////////////////
// Do some formatting
ws.Columns("B:G").Width = 20;
var rngTitle = ws.Range("B2:G2");
rngTitle.Style.Font.Bold = true;
rngTitle.Style.Fill.BackgroundColor = XLColor.Cyan;
ws.Columns().AdjustToContents();
ws = workbook.AddWorksheet("Test Whitespace");
ws.FirstCell().Value = "' ";
workbook.SaveAs(filePath);
}
}
}
}
+132
View File
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class Collections : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Collections");
// From a list of strings
var listOfStrings = new List<String>();
listOfStrings.Add("House");
listOfStrings.Add("Car");
ws.Cell(1, 1).Value = "Strings";
ws.Cell(1, 1).AsRange().AddToNamed("Titles");
ws.Cell(2, 1).Value = listOfStrings;
// From a list of arrays
var listOfArr = new List<Int32[]>();
listOfArr.Add(new Int32[] { 1, 2, 3 });
listOfArr.Add(new Int32[] { 1 });
listOfArr.Add(new Int32[] { 1, 2, 3, 4, 5, 6 });
ws.Cell(1, 3).Value = "Arrays";
ws.Range(1, 3, 1, 8).Merge().AddToNamed("Titles");
ws.Cell(2, 3).Value = listOfArr;
// From a DataTable
var dataTable = GetTable();
ws.Cell(6, 1).Value = "DataTable";
ws.Range(6, 1, 6, 4).Merge().AddToNamed("Titles");
ws.Cell(7, 1).Value = dataTable;
// From a query
var list = new List<Person>();
list.Add(new Person() { Name = "John", Age = 30, House = "On Elm St." });
list.Add(new Person() { Name = "Mary", Age = 15, House = "On Main St." });
list.Add(new Person() { Name = "Luis", Age = 21, House = "On 23rd St." });
list.Add(new Person() { Name = "Henry", Age = 45, House = "On 5th Ave." });
var people = from p in list
where p.Age >= 21
select new { p.Name, p.House, p.Age };
ws.Cell(6, 6).Value = "Query";
ws.Range(6, 6, 6, 8).Merge().AddToNamed("Titles");
ws.Cell(7, 6).Value = people;
// Prepare the style for the titles
var titlesStyle = wb.Style;
titlesStyle.Font.Bold = true;
titlesStyle.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
titlesStyle.Fill.BackgroundColor = XLColor.Cyan;
// Format all titles in one shot
wb.NamedRanges.NamedRange("Titles").Ranges.Style = titlesStyle;
ws.Columns().AdjustToContents();
wb.SaveAs(filePath);
}
class Person
{
public String House { get; set; }
public String Name { get; set; }
public Int32 Age { get; set; }
}
// Private
private DataTable GetTable()
{
DataTable table = new DataTable();
table.Columns.Add("Dosage", typeof(int));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Rows.Add(25, "Indocin", "David", new DateTime(2000, 1, 1));
table.Rows.Add(50, "Enebrel", "Sam", new DateTime(2000, 1, 2));
table.Rows.Add(10, "Hydralazine", "Christoff", new DateTime(2000, 1, 3));
table.Rows.Add(21, "Combivent", "Janet", new DateTime(2000, 1, 4));
table.Rows.Add(100, "Dilantin", "Melanie", new DateTime(2000, 1, 5));
return table;
}
// Override
#endregion
}
}
@@ -0,0 +1,114 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class CopyingRowsAndColumns : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var workbook = new XLWorkbook();
var originalSheet = workbook.Worksheets.Add("original");
originalSheet.Cell("A2").SetValue("test value");
originalSheet.Range("A2:E2").Merge();
originalSheet.Cell("F1").SetValue("test value").Style.Alignment.SetTopToBottom();
originalSheet.Range("F1:F6").Merge();
var fromRow = workbook.Worksheets.Add("From a Row");
fromRow.Cell(1, 1).SetValue("Row to Row:");
originalSheet.Row(2).CopyTo(fromRow.Row(2));
fromRow.Cell(3, 1).SetValue("Row to Range:");
originalSheet.Row(2).CopyTo(fromRow.Row(4).AsRange());
fromRow.Cell(5, 1).SetValue("Row to Cell:");
originalSheet.Row(2).CopyTo(fromRow.Row(6).FirstCell());
var fromRange = workbook.Worksheets.Add("From a Range");
fromRange.Cell(1, 1).SetValue("Range to Row:");
originalSheet.Row(2).AsRange().CopyTo(fromRange.Row(2));
fromRange.Cell(3, 1).SetValue("Range to Range:");
originalSheet.Row(2).AsRange().CopyTo(fromRange.Row(4).AsRange());
fromRange.Cell(5, 1).SetValue("Range to Cell:");
originalSheet.Row(2).AsRange().CopyTo(fromRange.Row(6).FirstCell());
CopyRowAsRange(originalSheet, 2, fromRange, 8);
var fromColumn = workbook.Worksheets.Add("From a Column to Column");
fromColumn.Cell(1, 1).SetValue("Column to Column:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").CopyTo(fromColumn.Column(2));
fromColumn.Cell(1, 3).SetValue("Column to Range:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").CopyTo(fromColumn.Column(4).AsRange());
fromColumn.Cell(1, 5).SetValue("Column to Cell:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").CopyTo(fromColumn.Column(6).FirstCell());
var fromRangeToColumn = workbook.Worksheets.Add("From a Range to Column");
fromRangeToColumn.Cell(1, 1).SetValue("Range to Column:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").AsRange().CopyTo(fromRangeToColumn.Column(2));
fromRangeToColumn.Cell(1, 3).SetValue("Range to Range:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").AsRange().CopyTo(fromRangeToColumn.Column(4).AsRange());
fromRangeToColumn.Cell(1, 5).SetValue("Range to Cell:").Style.Alignment.SetTopToBottom();
originalSheet.Column("F").AsRange().CopyTo(fromRangeToColumn.Column(6).FirstCell());
workbook.SaveAs(filePath);
}
private static void CopyRowAsRange(IXLWorksheet originalSheet, int originalRowNumber, IXLWorksheet destSheet, int destRowNumber)
{
{
var destinationRow = destSheet.Row(destRowNumber);
destinationRow.Clear();
var originalRow = originalSheet.Row(originalRowNumber);
int columnNumber = originalRow.LastCellUsed(XLCellsUsedOptions.All).Address.ColumnNumber;
var originalRange = originalSheet.Range(originalRowNumber, 1, originalRowNumber, columnNumber);
var destRange = destSheet.Range(destRowNumber, 1, destRowNumber, columnNumber);
originalRange.CopyTo(destRange);
}
}
// Private
// Override
#endregion
}
}
@@ -0,0 +1,44 @@
using ClosedXML.Excel;
using ClosedXML_Examples.Tables;
using System.IO;
namespace ClosedXML_Examples.Misc
{
public class CopyingWorksheets : IXLExample
{
public void Create(string filePath)
{
string tempFile1 = ExampleHelper.GetTempFilePath(filePath);
string tempFile2 = ExampleHelper.GetTempFilePath(filePath);
try
{
new UsingTables().Create(tempFile1);
var wb = new XLWorkbook(tempFile1);
var wsSource = wb.Worksheet(1);
// Copy the worksheet to a new sheet in this workbook
wsSource.CopyTo("Copy");
// We're going to open another workbook to show that you can
// copy a sheet from one workbook to another:
new BasicTable().Create(tempFile2);
var wbSource = new XLWorkbook(tempFile2);
wbSource.Worksheet(1).CopyTo(wb, "Copy From Other");
// Save the workbook with the 2 copies
wb.SaveAs(filePath);
}
finally
{
if (File.Exists(tempFile1))
{
File.Delete(tempFile1);
}
if (File.Exists(tempFile2))
{
File.Delete(tempFile2);
}
}
}
}
}
+227
View File
@@ -0,0 +1,227 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class DataTypes : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("Data Types");
var co = 2;
var ro = 1;
ws.Cell(++ro, co).Value = "Plain Text:";
ws.Cell(ro, co + 1).Value = "Hello World.";
ws.Cell(++ro, co).Value = "Plain Date:";
ws.Cell(ro, co + 1).Value = new DateTime(2010, 9, 2);
ws.Cell(++ro, co).Value = "Plain DateTime:";
ws.Cell(ro, co + 1).Value = new DateTime(2010, 9, 2, 13, 45, 22);
ws.Cell(++ro, co).Value = "Plain Boolean:";
ws.Cell(ro, co + 1).Value = true;
ws.Cell(++ro, co).Value = "Plain Number:";
ws.Cell(ro, co + 1).Value = 123.45;
ws.Cell(++ro, co).Value = "TimeSpan:";
ws.Cell(ro, co + 1).Value = new TimeSpan(33, 45, 22);
ro++;
ws.Cell(++ro, co).Value = "Decimal Number:";
ws.Cell(ro, co + 1).Value = 123.45m;
ws.Cell(++ro, co).Value = "Float Number:";
ws.Cell(ro, co + 1).Value = 123.45f;
ws.Cell(++ro, co).Value = "Double Number:";
ws.Cell(ro, co + 1).Value = 123.45d;
ws.Cell(++ro, co).Value = "Large Double Number:";
ws.Cell(ro, co + 1).Value = 9.999E307d;
ro++;
ws.Cell(++ro, co).Value = "Explicit Text:";
ws.Cell(ro, co + 1).Value = "'Hello World.";
ws.Cell(++ro, co).Value = "Date as Text:";
ws.Cell(ro, co + 1).Value = "'" + new DateTime(2010, 9, 2).ToString();
ws.Cell(++ro, co).Value = "DateTime as Text:";
ws.Cell(ro, co + 1).Value = "'" + new DateTime(2010, 9, 2, 13, 45, 22).ToString();
ws.Cell(++ro, co).Value = "Boolean as Text:";
ws.Cell(ro, co + 1).Value = "'" + true.ToString();
ws.Cell(++ro, co).Value = "Number as Text:";
ws.Cell(ro, co + 1).Value = "'123.45";
ws.Cell(++ro, co).Value = "Number with @ format:";
ws.Cell(ro, co + 1).Style.NumberFormat.Format = "@";
ws.Cell(ro, co + 1).Value = 123.45;
ws.Cell(++ro, co).Value = "Format number with @:";
ws.Cell(ro, co + 1).Value = 123.45;
ws.Cell(ro, co + 1).Style.NumberFormat.Format = "@";
ws.Cell(++ro, co).Value = "TimeSpan as Text:";
ws.Cell(ro, co + 1).Value = "'" + new TimeSpan(33, 45, 22).ToString();
ro++;
ws.Cell(++ro, co).Value = "Changing Data Types:";
ro++;
ws.Cell(++ro, co).Value = "Date to Text:";
ws.Cell(ro, co + 1).Value = new DateTime(2010, 9, 2);
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "DateTime to Text:";
ws.Cell(ro, co + 1).Value = new DateTime(2010, 9, 2, 13, 45, 22);
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "Boolean to Text:";
ws.Cell(ro, co + 1).Value = true;
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "Number to Text:";
ws.Cell(ro, co + 1).Value = 123.45;
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "TimeSpan to Text:";
ws.Cell(ro, co + 1).Value = new TimeSpan(33, 45, 22);
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "Text to Date:";
ws.Cell(ro, co + 1).Value = "'" + new DateTime(2010, 9, 2).ToString();
ws.Cell(ro, co + 1).DataType = XLDataType.DateTime;
ws.Cell(++ro, co).Value = "Text to DateTime:";
ws.Cell(ro, co + 1).Value = "'" + new DateTime(2010, 9, 2, 13, 45, 22).ToString();
ws.Cell(ro, co + 1).DataType = XLDataType.DateTime;
ws.Cell(++ro, co).Value = "Text to Boolean:";
ws.Cell(ro, co + 1).Value = "'" + true.ToString();
ws.Cell(ro, co + 1).DataType = XLDataType.Boolean;
ws.Cell(++ro, co).Value = "Text to Number:";
ws.Cell(ro, co + 1).Value = "'123.45";
ws.Cell(ro, co + 1).DataType = XLDataType.Number;
ws.Cell(++ro, co).Value = "Percentage Text to Number:";
ws.Cell(ro, co + 1).Value = "'55.12%";
ws.Cell(ro, co + 1).Style.NumberFormat.SetNumberFormatId((int)XLPredefinedFormat.Number.PercentPrecision2);
ws.Cell(ro, co + 1).DataType = XLDataType.Number;
ws.Cell(++ro, co).Value = "@ format to Number:";
ws.Cell(ro, co + 1).Style.NumberFormat.Format = "@";
ws.Cell(ro, co + 1).Value = 123.45;
ws.Cell(ro, co + 1).DataType = XLDataType.Number;
ws.Cell(++ro, co).Value = "Text to TimeSpan:";
ws.Cell(ro, co + 1).Value = "'" + new TimeSpan(33, 45, 22).ToString();
ws.Cell(ro, co + 1).DataType = XLDataType.TimeSpan;
ro++;
ws.Cell(++ro, co).Value = "Formatted Date to Text:";
ws.Cell(ro, co + 1).Value = new DateTime(2010, 9, 2);
ws.Cell(ro, co + 1).Style.DateFormat.Format = "yyyy-MM-dd";
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(++ro, co).Value = "Formatted Number to Text:";
ws.Cell(ro, co + 1).Value = 12345.6789;
ws.Cell(ro, co + 1).Style.NumberFormat.Format = "#,##0.00";
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ro++;
ws.Cell(++ro, co).Value = "Blank Text:";
ws.Cell(ro, co + 1).Value = 12345.6789;
ws.Cell(ro, co + 1).Style.NumberFormat.Format = "#,##0.00";
ws.Cell(ro, co + 1).DataType = XLDataType.Text;
ws.Cell(ro, co + 1).Value = "";
ro++;
// Using inline strings (few users will ever need to use this feature)
//
// By default all strings are stored as shared so one block of text
// can be reference by multiple cells.
// You can override this by setting the .ShareString property to false
ws.Cell(++ro, co).Value = "Inline String:";
var cell = ws.Cell(ro, co + 1);
cell.Value = "Not Shared";
cell.ShareString = false;
// To view all shared strings (all texts in the workbook actually), use the following:
// workbook.GetSharedStrings()
ws.Cell(++ro, co)
.SetDataType(XLDataType.Text)
.SetDataType(XLDataType.Boolean)
.SetDataType(XLDataType.DateTime)
.SetDataType(XLDataType.Number)
.SetDataType(XLDataType.TimeSpan)
.SetDataType(XLDataType.Text)
.SetDataType(XLDataType.TimeSpan)
.SetDataType(XLDataType.Number)
.SetDataType(XLDataType.DateTime)
.SetDataType(XLDataType.Boolean)
.SetDataType(XLDataType.Text);
ws.Columns(2, 3).AdjustToContents();
workbook.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
@@ -0,0 +1,35 @@
using System;
using ClosedXML.Excel;
using System.Threading;
using System.Globalization;
using System.IO;
namespace ClosedXML_Examples.Misc
{
public class DataTypesUnderDifferentCulture : IXLExample
{
public void Create(string filePath)
{
var backupCulture = Thread.CurrentThread.CurrentCulture;
// Set thread culture to French, which should format numbers using decimal COMMA
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("fr-FR");
string tempFile = ExampleHelper.GetTempFilePath(filePath);
try
{
new DataTypes().Create(tempFile);
var workbook = new XLWorkbook(tempFile);
workbook.SaveAs(filePath);
}
finally
{
Thread.CurrentThread.CurrentCulture = backupCulture;
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
}
}
}
}
+139
View File
@@ -0,0 +1,139 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class DataValidation : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Data Validation");
// Decimal between 1 and 5
ws.Cell(1, 1).SetDataValidation().Decimal.Between(1, 5);
// Whole number equals 2
var dv1 = ws.Range("A2:A3").SetDataValidation();
dv1.WholeNumber.EqualTo(2);
// Change the error message
dv1.ErrorStyle = XLErrorStyle.Warning;
dv1.ErrorTitle = "Number out of range";
dv1.ErrorMessage = "This cell only allows the number 2.";
// Date after the millenium
var dv2 = ws.Cell("A4").SetDataValidation();
dv2.Date.EqualOrGreaterThan(new DateTime(2000, 1, 1));
// Change the input message
dv2.InputTitle = "Can't party like it's 1999.";
dv2.InputMessage = "Please enter a date in this century.";
// From a list
ws.Cell("C1").Value = "Yes";
ws.Cell("C2").Value = "No";
ws.Cell("A5").SetDataValidation().List(ws.Range("C1:C2"));
ws.Range("C1:C2").AddToNamed("YesNo");
ws.Cell("A6").SetDataValidation().List("=YesNo");
// Intersecting dataValidations
ws.Range("B1:B4").SetDataValidation().WholeNumber.EqualTo(1);
ws.Range("B3:B4").SetDataValidation().WholeNumber.EqualTo(2);
// Validate with multiple ranges
var ws2 = wb.Worksheets.Add("Validate Ranges");
var rng1 = ws2.Ranges("A1:B2,B4:D7,F4:G5");
rng1.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng1Validation = rng1.SetDataValidation();
rng1Validation.Decimal.EqualTo(1);
rng1Validation.IgnoreBlanks = false;
var rng2 = ws2.Range("A11:E14");
rng2.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng2Validation = rng2.SetDataValidation();
rng2Validation.Decimal.EqualTo(2);
rng2Validation.IgnoreBlanks = false;
var rng3 = ws2.Range("B2:B12");
//rng3.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng3Validation = rng3.SetDataValidation();
rng3Validation.Decimal.EqualTo(3);
rng3Validation.IgnoreBlanks = true;
var rng4 = ws2.Range("D5:D6");
//rng4.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng4Validation = rng4.SetDataValidation();
rng4Validation.Decimal.EqualTo(4);
rng4Validation.IgnoreBlanks = true;
var rng5 = ws2.Range("C13:C14");
//rng5.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng5Validation = rng5.SetDataValidation();
rng5Validation.Decimal.EqualTo(5);
rng5Validation.IgnoreBlanks = true;
var rng6 = ws2.Range("D11:D12");
//rng6.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng6Validation = rng6.SetDataValidation();
rng6Validation.Decimal.EqualTo(5);
rng6Validation.IgnoreBlanks = true;
var rng7 = ws2.Range("G4:G5");
//rng7.Style.Fill.SetBackgroundColor(XLColor.YellowGreen);
var rng7Validation = rng7.SetDataValidation();
rng7Validation.Decimal.EqualTo(5);
rng7Validation.IgnoreBlanks = true;
ws.CopyTo(ws.Name + " - Copy");
ws2.CopyTo(ws2.Name + " - Copy");
wb.AddWorksheet("Copy From Range 1").FirstCell().Value = ws.RangeUsed(XLCellsUsedOptions.All);
wb.AddWorksheet("Copy From Range 2").FirstCell().Value = ws2.RangeUsed(XLCellsUsedOptions.All);
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+79
View File
@@ -0,0 +1,79 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class Formulas : IXLExample
{
public virtual void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Formulas");
ws.Cell(1, 1).Value = "Num1";
ws.Cell(1, 2).Value = "Num2";
ws.Cell(1, 3).Value = "Total";
ws.Cell(1, 4).Value = "cell.FormulaA1";
ws.Cell(1, 5).Value = "cell.FormulaR1C1";
ws.Cell(1, 6).Value = "cell.Value";
ws.Cell(1, 7).Value = "Are Equal?";
ws.Cell(2, 1).Value = 1;
ws.Cell(2, 2).Value = 2;
var cellWithFormulaA1 = ws.Cell(2, 3);
// Use A1 notation
cellWithFormulaA1.FormulaA1 = "=A2+$B$2"; // The equal sign (=) in a formula is optional
ws.Cell(2, 4).Value = cellWithFormulaA1.FormulaA1;
ws.Cell(2, 5).Value = cellWithFormulaA1.FormulaR1C1;
ws.Cell(2, 6).Value = cellWithFormulaA1.Value;
ws.Cell(3, 1).Value = 1;
ws.Cell(3, 2).Value = 2;
var cellWithFormulaR1C1 = ws.Cell(3, 3);
// Use R1C1 notation
cellWithFormulaR1C1.FormulaR1C1 = "RC[-2]+R3C2"; // The equal sign (=) in a formula is optional
ws.Cell(3, 4).Value = cellWithFormulaR1C1.FormulaA1;
ws.Cell(3, 5).Value = cellWithFormulaR1C1.FormulaR1C1;
ws.Cell(3, 6).Value = cellWithFormulaR1C1.Value;
ws.Cell(4, 1).Value = "A";
ws.Cell(4, 2).Value = "B";
var cellWithStringFormula = ws.Cell(4, 3);
// Use R1C1 notation
cellWithStringFormula.FormulaR1C1 = "=\"Test\" & RC[-2] & \"R3C2\"";
ws.Cell(4, 4).Value = cellWithStringFormula.FormulaA1;
ws.Cell(4, 5).Value = cellWithStringFormula.FormulaR1C1;
ws.Cell(4, 6).Value = cellWithStringFormula.Value;
// Setting the formula of a range
var rngData = ws.Range(2, 1, 4, 7);
rngData.LastColumn().FormulaR1C1 = "=IF(RC[-4]=RC[-1],\"Yes\", \"No\")";
// Using an array formula:
// Just put the formula between curly braces
ws.Cell("A6").Value = "Array Formula: ";
ws.Cell("B6").FormulaA1 = "{A2+A3}";
ws.Range("C6:D6").FormulaA1 = "{TRANSPOSE(A2:A3)}";
ws.Range(1, 1, 1, 7).Style.Fill.BackgroundColor = XLColor.Cyan;
ws.Range(1, 1, 1, 7).Style.Font.Bold = true;
ws.Columns().AdjustToContents();
// You can also change the reference notation:
wb.ReferenceStyle = XLReferenceStyle.R1C1;
// And the workbook calculation mode:
wb.CalculateMode = XLCalculateMode.Auto;
ws.Range("A10").AddToNamed("A10_R1C1_A10_R1C1");
ws.Cell("A10").Value = 0;
ws.Cell("A11").FormulaA1 = "A2 + A10_R1C1_A10_R1C1";
ws.Cell("A12").FormulaR1C1 = "R2C1 + A10_R1C1_A10_R1C1";
ws.Cell("A13").FormulaR1C1 = "=SUM(R[-5]:R[-4])";
ws.Cell("A14").FormulaA1 = "=SUM(8:9)";
wb.SaveAs(filePath);
}
}
}
@@ -0,0 +1,16 @@
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class FormulasWithEvaluation : Formulas
{
public override void Create(string filePath)
{
base.Create(filePath);
using (var wb = new XLWorkbook(filePath))
{
wb.Save(true, true);
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class FreezePanes : IXLExample
{
public void Create(String filePath)
{
using (var wb = new XLWorkbook())
{
// Freeze rows and columns in one shot
var ws1 = wb.AddWorksheet("Freeze1");
ws1.Cell(5, 5).SetActive();
ws1.SheetView.Freeze(3, 3);
// You can also be more specific on what you want to freeze
// For example:
var ws2 = wb.AddWorksheet("FreezeRows");
ws2.Cell(5, 5).SetActive();
ws2.SheetView.FreezeRows(3);
var ws3 = wb.AddWorksheet("FreezeColumns");
ws3.Cell(5, 5).SetActive();
ws3.SheetView.FreezeColumns(3);
var wsSplit = wb.AddWorksheet("Split View");
wsSplit.Cell(2, 2).SetActive();
wsSplit.SheetView.SplitRow = 3;
wsSplit.SheetView.SplitColumn = 3;
wb.SaveAs(filePath);
}
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class HideSheets : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
wb.Worksheets.Add("First Hidden").Hide();
wb.Worksheets.Add("Visible");
wb.Worksheets.Add("Unhidden").Hide().Unhide();
wb.Worksheets.Add("VeryHidden").Visibility = XLWorksheetVisibility.VeryHidden;
wb.Worksheets.Add("Last Hidden").Hide();
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+64
View File
@@ -0,0 +1,64 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class HideUnhide : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Hide Rows Columns");
ws.Columns(1, 3).Hide();
ws.Rows(1, 3).Hide();
ws.Column(2).Unhide();
ws.Row(2).Unhide();
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+128
View File
@@ -0,0 +1,128 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class Hyperlinks : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Hyperlinks");
wb.Worksheets.Add("Second Sheet");
Int32 ro = 0;
// You can create a link with pretty much anything you can put on a
// browser: http, ftp, mailto, gopher, news, nntp, etc.
ws.Cell(++ro, 1).Value = "Link to a web page, no tooltip - Yahoo!";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink(@"http://www.yahoo.com");
ws.Cell(++ro, 1).Value = "Link to a web page, with a tooltip - Yahoo!";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink(@"http://www.yahoo.com", "Click to go to Yahoo!");
ws.Cell(++ro, 1).Value = "Link to a file - same folder";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink("Test.xlsx");
ws.Cell(++ro, 1).Value = "Link to a file - Absolute";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink(@"D:\Test.xlsx");
ws.Cell(++ro, 1).Value = "Link to a file - relative address";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink(@"../Test.xlsx");
ws.Cell(++ro, 1).Value = "Link to an address in this worksheet";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink("B1");
ws.Cell(++ro, 1).Value = "Link to an address in another worksheet";
ws.Cell(ro, 1).Hyperlink = new XLHyperlink("'Second Sheet'!A1");
// You can also set the properties of a hyperlink directly:
ws.Cell(++ro, 1).Value = "Link to a range in this worksheet";
ws.Cell(ro, 1).Hyperlink.InternalAddress = "B1:C2";
ws.Cell(ro, 1).Hyperlink.Tooltip = "SquareBox";
ws.Cell(++ro, 1).Value = "Link to an email message";
ws.Cell(ro, 1).Hyperlink.ExternalAddress = new Uri(@"mailto:SantaClaus@NorthPole.com?subject=Presents");
// Deleting a hyperlink
ws.Cell(++ro, 1).Value = "This is no longer a link";
ws.Cell(ro, 1).Hyperlink.InternalAddress = "A1";
ws.Cell(ro, 1).Hyperlink.Delete();
// Setting a hyperlink preserves previous formatting:
ws.Cell(++ro, 1).Value = "Odd looking link";
ws.Cell(ro, 1).Style.Font.FontColor = XLColor.Red;
ws.Cell(ro, 1).Style.Font.Underline = XLFontUnderlineValues.Double;
ws.Cell(ro, 1).Hyperlink = new XLHyperlink(ws.Range("B1:C2"));
// Hyperlink via formula
ws.Cell( ++ro, 1 ).SetValue( "Send Email" )
.SetFormulaA1( "=HYPERLINK(\"mailto:test@test.com\", \"Send Email\")" )
.Hyperlink = new XLHyperlink( "mailto:test@test.com", "'Send Email'" );
// List all hyperlinks in a worksheet:
var hyperlinksInWorksheet = ws.Hyperlinks;
// List all hyperlinks in a range:
var hyperlinksInRange = ws.Range("A1:A3").Hyperlinks;
// Clearing a cell with a hyperlink
ws.Cell(++ro, 1).Value = "ERROR!";
ws.Cell(ro, 1).Hyperlink.InternalAddress = "A1";
ws.Cell(ro, 1).Clear();
// Deleting a cell with a hyperlink
ws.Cell(++ro, 1).Value = "ERROR!";
ws.Cell(ro, 1).Hyperlink.InternalAddress = "A1";
ws.Cell(ro, 1).Clear();
ws.Columns().AdjustToContents();
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+110
View File
@@ -0,0 +1,110 @@
using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
namespace ClosedXML_Examples.Misc
{
public class InsertingData : IXLExample
{
#region Methods
// Public
public void Create(String filePath)
{
using (var wb = new XLWorkbook())
{
var ws = wb.Worksheets.Add("Inserting Data");
// From a list of strings
var listOfStrings = new List<String>();
listOfStrings.Add("House");
listOfStrings.Add("001");
ws.Cell(1, 1).Value = "From Strings";
ws.Cell(1, 1).AsRange().AddToNamed("Titles");
ws.Cell(2, 1).InsertData(listOfStrings);
// From a list of arrays
var listOfArr = new List<Int32[]>();
listOfArr.Add(new Int32[] { 1, 2, 3 });
listOfArr.Add(new Int32[] { 1 });
listOfArr.Add(new Int32[] { 1, 2, 3, 4, 5, 6 });
ws.Cell(1, 3).Value = "From Arrays";
ws.Range(1, 3, 1, 8).Merge().AddToNamed("Titles");
ws.Cell(2, 3).InsertData(listOfArr);
// From a DataTable
var dataTable = GetTable();
ws.Cell(6, 1).Value = "From DataTable";
ws.Range(6, 1, 6, 4).Merge().AddToNamed("Titles");
ws.Cell(7, 1).InsertData(dataTable);
// From a query
var list = new List<Person>();
list.Add(new Person() { Name = "John", Age = 30, House = "On Elm St." });
list.Add(new Person() { Name = "Mary", Age = 15, House = "On Main St." });
list.Add(new Person() { Name = "Luis", Age = 21, House = "On 23rd St." });
list.Add(new Person() { Name = "Henry", Age = 45, House = "On 5th Ave." });
var people = from p in list
where p.Age >= 21
select new { p.Name, p.House, p.Age };
ws.Cell(6, 6).Value = "From Query";
ws.Range(6, 6, 6, 8).Merge().AddToNamed("Titles");
ws.Cell(7, 6).InsertData(people);
ws.Cell(11, 6).Value = "From List";
ws.Range(11, 6, 11, 9).Merge().AddToNamed("Titles");
ws.Cell(12, 6).InsertData(list);
ws.Cell("A13").Value = "Transposed";
ws.Range(13, 1, 13, 3).Merge().AddToNamed("Titles");
ws.Cell("A14").InsertData(people.AsEnumerable(), true);
// Prepare the style for the titles
var titlesStyle = wb.Style;
titlesStyle.Font.Bold = true;
titlesStyle.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
titlesStyle.Fill.BackgroundColor = XLColor.Cyan;
// Format all titles in one shot
wb.NamedRanges.NamedRange("Titles").Ranges.Style = titlesStyle;
ws.Columns().AdjustToContents();
wb.SaveAs(filePath);
}
}
private class Person
{
public String House { get; set; }
public String Name { get; set; }
public Int32 Age { get; set; }
public static String ClassType { get { return nameof(Person); } }
}
// Private
private DataTable GetTable()
{
DataTable table = new DataTable();
table.Columns.Add("Dosage", typeof(int));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
table.Rows.Add(25, "Indocin", "David", new DateTime(2000, 1, 1));
table.Rows.Add(50, "Enebrel", "Sam", new DateTime(2000, 1, 2));
table.Rows.Add(10, "Hydralazine", "Christoff", new DateTime(2000, 1, 3));
table.Rows.Add(21, "Combivent", "Janet", new DateTime(2000, 1, 4));
table.Rows.Add(100, "Dilantin", "Melanie", new DateTime(2000, 1, 5));
return table;
}
// Override
#endregion Methods
}
}
@@ -0,0 +1,57 @@
using System.IO;
using System.Linq;
using ClosedXML.Excel;
using MoreLinq;
namespace ClosedXML_Examples
{
public class LambdaExpressions : IXLExample
{
public void Create(string filePath)
{
string tempFile = ExampleHelper.GetTempFilePath(filePath);
try
{
new BasicTable().Create(tempFile);
var workbook = new XLWorkbook(tempFile);
var ws = workbook.Worksheet(1);
// Define a range with the data
var firstDataCell = ws.Cell("B4");
var lastDataCell = ws.LastCellUsed();
var rngData = ws.Range(firstDataCell.Address, lastDataCell.Address);
// Delete all rows where Outcast = false (the 3rd column)
rngData.Rows() // From all rows
.Where(r => !r.Cell(3).GetBoolean()) // where the 3rd cell of each row is false
.ForEach(r => r.Delete()); // delete the row and shift the cells up (the default for rows in a range)
//// Put a light gray background to all text cells
//rngData.Cells() // From all cells
// .Where(c => c.DataType == XLCellValues.Text) // where the data type is Text
// .ForEach(c => c.Style.Fill.BackgroundColor = XLColor.LightGray); // Fill with a light gray
var cells = rngData.Cells();
var filtered = cells.Where(c => c.DataType == XLDataType.Text);
var list = filtered.ToList();
foreach (var c in list)
{
c.Style.Fill.BackgroundColor = XLColor.LightGray;
}
// Put a thick border to the bottom of the table (we may have deleted the bottom cells with the border)
rngData.LastRow().Style.Border.BottomBorder = XLBorderStyleValues.Thick;
workbook.SaveAs(filePath);
}
finally
{
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
}
}
}
}
+88
View File
@@ -0,0 +1,88 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class MergeCells : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Constructors
// Public
// Private
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var workbook = new XLWorkbook();
var ws = workbook.Worksheets.Add("Merge Cells");
// Merge a row
ws.Cell("B2").Value = "Merged Row(1) of Range (B2:D3)";
ws.Range("B2:D3").Row(1).Merge();
// Merge a column
ws.Cell("F2").Value = "Merged Column(1) of Range (F2:G8)";
ws.Cell("F2").Style.Alignment.WrapText = true;
ws.Range("F2:G8").Column(1).Merge();
// Merge a range
ws.Cell("B4").Value = "Merged Range (B4:D6)";
ws.Cell("B4").Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
ws.Cell("B4").Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;
ws.Range("B4:D6").Merge();
// Unmerging a range...
ws.Cell("B8").Value = "Unmerged";
ws.Range("B8:D8").Merge();
ws.Range("B8:D8").Unmerge();
workbook.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+53
View File
@@ -0,0 +1,53 @@
using System.IO;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class MergeMoves : IXLExample
{
public void Create(string filePath)
{
string tempFile = ExampleHelper.GetTempFilePath(filePath);
try
{
new MergeCells().Create(tempFile);
var workbook = new XLWorkbook(tempFile);
var ws = workbook.Worksheet(1);
ws.Range("B1:F1").InsertRowsBelow(1);
ws.Range("A3:A9").InsertColumnsAfter(1);
ws.Row(1).Delete();
ws.Column(1).Delete();
ws.Range("E8:E9").InsertColumnsAfter(1);
ws.Range("F2:F8").Merge();
ws.Range("E3:E4").InsertColumnsAfter(1);
ws.Range("F2:F8").Merge();
ws.Range("E1:E2").InsertColumnsAfter(1);
ws.Range("G2:G8").Merge();
ws.Range("E1:E2").Delete(XLShiftDeletedCells.ShiftCellsLeft);
ws.Range("D3:E3").InsertRowsBelow(1);
ws.Range("A1:B1").InsertRowsBelow(1);
ws.Range("B3:D3").Merge();
ws.Range("A1:B1").Delete(XLShiftDeletedCells.ShiftCellsUp);
ws.Range("B8:D8").Merge();
ws.Range("D8:D9").Clear();
workbook.SaveAs(filePath);
}
finally
{
if (File.Exists(tempFile))
{
File.Delete(tempFile);
}
}
}
}
}
+30
View File
@@ -0,0 +1,30 @@
using System.Linq;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class MultipleSheets : IXLExample
{
public void Create(string filePath)
{
var wb = new XLWorkbook();
foreach (var wsNum in Enumerable.Range(1, 5))
{
wb.Worksheets.Add("Original Pos. is " + wsNum.ToString());
}
// Move first worksheet to the last position
wb.Worksheet(1).Position = wb.Worksheets.Count() + 1;
// Delete worksheet on position 4 (in this case it's where original position = 5)
wb.Worksheet(4).Delete();
// Swap sheets in positions 1 and 2
wb.Worksheet(2).Position = 1;
wb.SaveAs(filePath);
}
}
}
+86
View File
@@ -0,0 +1,86 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class Outline : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Outline");
ws.Outline.SummaryHLocation = XLOutlineSummaryHLocation.Right;
ws.Columns(2, 6).Group(); // Create an outline (level 1) for columns 2-6
ws.Columns(2, 4).Group(); // Create an outline (level 2) for columns 2-4
ws.Column(2).Ungroup(true); // Remove column 2 from all outlines
ws.Outline.SummaryVLocation = XLOutlineSummaryVLocation.Bottom;
ws.Rows(1, 5).Group(); // Create an outline (level 1) for rows 1-5
ws.Rows(1, 4).Group(); // Create an outline (level 2) for rows 1-4
ws.Rows(1, 4).Collapse(); // Collapse rows 1-4
ws.Rows(1, 2).Group(); // Create an outline (level 3) for rows 1-2
ws.Rows(1, 2).Ungroup(); // Ungroup rows 1-2 from their last outline
// You can also Collapse/Expand specific outline levels
//
// ws.CollapseRows(Int32 outlineLevel)
// ws.CollapseColumns(Int32 outlineLevel)
//
// ws.ExpandRows(Int32 outlineLevel)
// ws.ExpandColumns(Int32 outlineLevel)
// And you can also Collapse/Expand ALL outline levels in one shot
//
// ws.CollapseRows()
// ws.CollapseColumns()
//
// ws.ExpandRows()
// ws.ExpandColumns()
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+21
View File
@@ -0,0 +1,21 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples.Misc
{
public class RightToLeft : IXLExample
{
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("RightToLeftSheet");
ws.Cell("A1").Value = "A1";
ws.Cell("B1").Value = "B1";
ws.Cell("C1").Value = "C1";
ws.RightToLeft = true;
wb.SaveAs(filePath);
}
}
}
@@ -0,0 +1,58 @@
using ClosedXML.Excel;
using System;
using static ClosedXML.Excel.XLProtectionAlgorithm;
namespace ClosedXML_Examples.Misc
{
public class SheetProtection : IXLExample
{
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Protected No-Password");
ws.Protect().AllowElement
(
// On this sheet we will only allow:
XLSheetProtectionElements.FormatCells
| XLSheetProtectionElements.InsertColumns
| XLSheetProtectionElements.DeleteColumns
| XLSheetProtectionElements.DeleteRows
| XLSheetProtectionElements.EditScenarios
);
ws.Cell("A1").SetValue("Locked, No Hidden (Default):").Style.Font.SetBold().Fill.SetBackgroundColor(XLColor.Cyan);
ws.Cell("B1").Style
.Border.SetOutsideBorder(XLBorderStyleValues.Medium);
ws.Cell("A2").SetValue("Locked, Hidden:").Style.Font.SetBold().Fill.SetBackgroundColor(XLColor.Cyan);
ws.Cell("B2").Style
.Protection.SetHidden()
.Border.SetOutsideBorder(XLBorderStyleValues.Medium);
ws.Cell("A3").SetValue("Not Locked, Hidden:").Style.Font.SetBold().Fill.SetBackgroundColor(XLColor.Cyan);
ws.Cell("B3").Style
.Protection.SetLocked(false)
.Protection.SetHidden()
.Border.SetOutsideBorder(XLBorderStyleValues.Medium);
ws.Cell("A4").SetValue("Not Locked, Not Hidden:").Style.Font.SetBold().Fill.SetBackgroundColor(XLColor.Cyan);
ws.Cell("B4").Style
.Protection.SetLocked(false)
.Border.SetOutsideBorder(XLBorderStyleValues.Medium);
ws.Columns().AdjustToContents();
// Protect a sheet with a password
var protectedSheet = wb.Worksheets.Add("Protected Password = 123");
var protection = protectedSheet.Protect("123", Algorithm.SimpleHash);
protection.AllowElement
(
XLSheetProtectionElements.InsertRows
| XLSheetProtectionElements.InsertColumns
);
wb.SaveAs(filePath);
}
}
}
+44
View File
@@ -0,0 +1,44 @@
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class SheetViews : IXLExample
{
public void Create(string filePath)
{
using (var wb = new XLWorkbook())
{
IXLWorksheet ws;
ws = wb.AddWorksheet("ZoomScale");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScale = 50;
ws = wb.AddWorksheet("ZoomScaleNormal");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScaleNormal = 70;
ws = wb.AddWorksheet("ZoomScalePageLayoutView");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScalePageLayoutView = 85;
ws = wb.AddWorksheet("ZoomScaleSheetLayoutView");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScaleSheetLayoutView = 120;
ws = wb.AddWorksheet("ZoomScaleTooSmall");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScale = 5;
ws = wb.AddWorksheet("ZoomScaleTooBig");
ws.FirstCell().SetValue(ws.Name);
ws.SheetView.ZoomScale = 500;
ws = wb.AddWorksheet("TopLeftCell");
ws.SheetView.TopLeftCellAddress = ws.Cell("AZ2000").Address;
wb.SaveAs(filePath);
}
}
}
}
@@ -0,0 +1,93 @@
using System;
using System.Linq;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class ShiftingFormulas : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Shifting Formulas");
ws.Cell("B2").Value = 5;
ws.Cell("B3").Value = 6;
ws.Cell("C2").Value = 1;
ws.Cell("C3").Value = 2;
ws.Cell("A4").Value = "Sum:";
ws.Range("B4:C4").FormulaR1C1 = "Sum(R[-2]C:R[-1]C)";
ws.Range("B4:C4").AddToNamed("WorkbookB4C4");
ws.Range("B4:C4").AddToNamed("WorksheetB4C4", XLScope.Worksheet);
ws.Cell("E2").Value = "Avg:";
ws.Cell("F2").FormulaA1 = "Average(B2:C3)";
ws.Ranges("A4,E2").Style
.Font.SetBold()
.Fill.SetBackgroundColor(XLColor.CyanProcess);
var ws2 = wb.Worksheets.Add("WS2");
ws2.Cell(1, 1).FormulaA1 = "='Shifting Formulas'!B2";
ws2.Cell(1, 2).Value = ws2.Cell(1, 1).Value;
ws2.Cell(2, 1).FormulaA1 = "Average('Shifting Formulas'!$B$2:$C$3)";
ws2.Cell(3, 1).FormulaA1 = "Average('Shifting Formulas'!$B$2:$C3)";
ws2.Cell(4, 1).FormulaA1 = "Average('Shifting Formulas'!$B$2:C3)";
ws2.Cell(5, 1).FormulaA1 = "Average('Shifting Formulas'!$B2:C3)";
ws2.Cell(6, 1).FormulaA1 = "Average('Shifting Formulas'!B2:C3)";
ws2.Cell(7, 1).FormulaA1 = "Average('Shifting Formulas'!B2:C$3)";
ws2.Cell(8, 1).FormulaA1 = "Average('Shifting Formulas'!B2:$C$3)";
ws2.Cell(9, 1).FormulaA1 = "Average('Shifting Formulas'!B$2:$C$3)";
var dataGrid = ws.Range("B2:D3");
ws.Row(1).InsertRowsAbove(1);
var newRow = dataGrid.LastRow().InsertRowsAbove(1).First();
newRow.Value = 1;
dataGrid.LastColumn().FormulaR1C1 = String.Format("SUM(RC[-{0}]:RC[-1])", dataGrid.ColumnCount() - 1);
ws.Cell(1, 1).InsertCellsBelow(1);
ws.Column(1).InsertColumnsBefore(1);
ws.Row(4).Delete();
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
+104
View File
@@ -0,0 +1,104 @@
using ClosedXML.Excel;
using System;
namespace ClosedXML_Examples
{
public class ShowCase : IXLExample
{
public void Create(String filePath)
{
// Creating a new workbook
var wb = new XLWorkbook();
//Adding a worksheet
var ws = wb.Worksheets.Add("Contacts");
//Adding text
//Title
ws.Cell("B2").Value = "Contacts";
//First Names
ws.Cell("B3").Value = "FName";
ws.Cell("B4").Value = "John";
ws.Cell("B5").Value = "Hank";
ws.Cell("B6").SetValue("Dagny"); // Another way to set the value
//Last Names
ws.Cell("C3").Value = "LName";
ws.Cell("C4").Value = "Galt";
ws.Cell("C5").Value = "Rearden";
ws.Cell("C6").SetValue("Taggart"); // Another way to set the value
//Adding more data types
//Is an outcast?
ws.Cell("D3").Value = "Outcast";
ws.Cell("D4").Value = true;
ws.Cell("D5").Value = false;
ws.Cell("D6").SetValue(false); // Another way to set the value
//Date of Birth
ws.Cell("E3").Value = "DOB";
ws.Cell("E4").Value = new DateTime(1919, 1, 21);
ws.Cell("E5").Value = new DateTime(1907, 3, 4);
ws.Cell("E6").SetValue(new DateTime(1921, 12, 15)); // Another way to set the value
//Income
ws.Cell("F3").Value = "Income";
ws.Cell("F4").Value = 2000;
ws.Cell("F5").Value = 40000;
ws.Cell("F6").SetValue(10000); // Another way to set the value
//Defining ranges
//From worksheet
var rngTable = ws.Range("B2:F6");
//From another range
var rngDates = rngTable.Range("E4:E6");
var rngNumbers = rngTable.Range("F4:F6");
//Formatting dates and numbers
//Using a OpenXML's predefined formats
rngDates.Style.NumberFormat.NumberFormatId = 15;
//Using a custom format
rngNumbers.Style.NumberFormat.Format = "$ #,##0";
//Format title cell in one shot
rngTable.Cell(1, 1).Style
.Font.SetBold()
.Fill.SetBackgroundColor(XLColor.CornflowerBlue)
.Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);
//Merge title cells
rngTable.FirstRow().Merge(); // We could've also used: rngTable.Range("A1:E1").Merge() or rngTable.Row(1).Merge()
//Formatting headers
var rngHeaders = rngTable.Range("B3:F3");
rngHeaders.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
rngHeaders.Style.Font.Bold = true;
rngHeaders.Style.Font.FontColor = XLColor.DarkBlue;
rngHeaders.Style.Fill.BackgroundColor = XLColor.Aqua;
// Create an Excel table with the data portion
var rngData = ws.Range("B3:F6");
var excelTable = rngData.CreateTable();
// Add the totals row
excelTable.ShowTotalsRow = true;
// Put the average on the field "Income"
// Notice how we're calling the cell by the column name
excelTable.Field("Income").TotalsRowFunction = XLTotalsRowFunction.Average;
// Put a label on the totals cell of the field "DOB"
excelTable.Field("DOB").TotalsRowLabel = "Average:";
//Add thick borders to the contents of our spreadsheet
ws.RangeUsed().Style.Border.OutsideBorder = XLBorderStyleValues.Thick;
// You can also specify the border for each side with:
// contents.FirstColumn().Style.Border.LeftBorder = XLBorderStyleValues.Thick;
// contents.LastColumn().Style.Border.RightBorder = XLBorderStyleValues.Thick;
// contents.FirstRow().Style.Border.TopBorder = XLBorderStyleValues.Thick;
// contents.LastRow().Style.Border.BottomBorder = XLBorderStyleValues.Thick;
// Adjust column widths to their content
ws.Columns(2, 6).AdjustToContents();
//Saving the workbook
wb.SaveAs(filePath);
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class TabColors : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var wsRed = wb.Worksheets.Add("Red").SetTabColor(XLColor.Red);
var wsAccent3 = wb.Worksheets.Add("Accent3").SetTabColor(XLColor.FromTheme(XLThemeColor.Accent3));
var wsIndexed = wb.Worksheets.Add("Indexed");
wsIndexed.TabColor = XLColor.FromIndex(24);
var wsArgb = wb.Worksheets.Add("Argb");
wsArgb.TabColor = XLColor.FromArgb(23, 23, 23);
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
@@ -0,0 +1,75 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class WorkbookProperties : IXLExample
{
#region Variables
// Public
// Private
#endregion
#region Properties
// Public
// Private
// Override
#endregion
#region Events
// Public
// Private
// Override
#endregion
#region Methods
// Public
public void Create(String filePath)
{
var wb = new XLWorkbook();
var ws = wb.Worksheets.Add("Workbook Properties");
wb.Properties.Author = "theAuthor";
wb.Properties.Title = "theTitle";
wb.Properties.Subject = "theSubject";
wb.Properties.Category = "theCategory";
wb.Properties.Keywords = "theKeywords";
wb.Properties.Comments = "theComments";
wb.Properties.Status = "theStatus";
wb.Properties.LastModifiedBy = "theLastModifiedBy";
wb.Properties.Company = "theCompany";
wb.Properties.Manager = "theManager";
// Creating/Using custom properties
wb.CustomProperties.Add("theText", "XXX");
wb.CustomProperties.Add("theDate", new DateTime(2011, 1, 1, 17, 0, 0, DateTimeKind.Utc)); // Use UTC to make sure test can be run in any time zone
wb.CustomProperties.Add("theNumber", 123.456);
wb.CustomProperties.Add("theBoolean", true);
wb.SaveAs(filePath);
}
// Private
// Override
#endregion
}
}
@@ -0,0 +1,23 @@
using System;
using ClosedXML.Excel;
namespace ClosedXML_Examples.Misc
{
public class WorkbookProtection : IXLExample
{
#region Methods
// Public
public void Create(String filePath)
{
using (var wb = new XLWorkbook())
{
var ws = wb.Worksheets.Add("Workbook Protection");
wb.Protect(true, false, "Abc@123");
wb.SaveAs(filePath);
}
}
#endregion
}
}