Below is the code we use to convert a Range to a DataTable.
We had an issue with certain dateformats being the Julian # of days since 1/1/1900 so this tries to convert those. This also converts RichText to HTML:
We had an issue with certain dateformats being the Julian # of days since 1/1/1900 so this tries to convert those. This also converts RichText to HTML:
public static DataTable RangeToDataTable(IXLRange range, bool firstLineHeadings = true)
{
if (range.IsMerged())
{
range = range.Unmerge(); // Unmerge any merged cells
}
DataTable dt = new DataTable();
// First just do headers (1st row in Range)
int columnCnt = range.ColumnCount();
for (int k = 1; k <= columnCnt; k++)
{
var name = range.Row(1).Cell(k).Address.ColumnLetter;
if (firstLineHeadings) name = range.Row(1).Cell(k).GetString();
dt.Columns.Add(name);
}
bool firstRow = true;
foreach (var myrow in range.RowsUsed()) // RowsUsed seems to also make merged called all report the same value (which we want)
{
if (firstRow && firstLineHeadings) { firstRow = false; continue; }
if (myrow.IsEmpty()) continue;
DataRow workRow = dt.NewRow();
for (int j = 1; j <= columnCnt; j++)
{
IXLCell cellObj = myrow.Cell(j); // not 0 based
var cellValue = cellObj.Value;
var checkForDate = cellObj.GetFormattedString();
if (checkForDate.Contains("-yy") && checkForDate.Contains("[$-"))
cellValue = FromExcelSerialDate(cellValue);
else
{
if (cellObj.HasHyperlink && cellObj.Hyperlink.IsExternal) cellValue = "<a href='" + cellObj.Hyperlink.ExternalAddress + "'>" + cellObj.Value + "</a>";
if (cellObj.HasRichText) cellValue = RichTextToHTML(cellObj); // If the link is formatted this overwrites with the prettier link
}
workRow[j - 1] = cellValue; // 0 based in DataRow object for [] indexing
}
dt.Rows.Add(workRow);
}
return dt;
}
public static DateTime FromExcelSerialDate(object serialDate)
{
int excelNumber = int.Parse(serialDate.ToString());
if (excelNumber > 59) excelNumber -= 1; //Excel/Lotus 2/29/1900 bug
return new DateTime(1899, 12, 31).AddDays(excelNumber);
}
public static string RichTextToHTML(IXLCell cell)
{
StringBuilder myString = new StringBuilder();
// Special case when the whole cell has a link vs. a http:// string in one of the rich text parts below in the loop
if (cell.HasHyperlink && cell.Hyperlink.IsExternal) myString.Append("<a href='" + cell.Hyperlink.ExternalAddress + "'>");
foreach (var richText in cell.RichText)
{
myString.Append("<span style='"); // Start SPAN and CSS here then add to it below
if (richText.Bold) myString.Append("font-weight: bold;");
if (richText.Strikethrough) myString.Append("text-decoration:line-through;");
if (richText.Italic) myString.Append("font-style: italic;");
if (richText.Underline == XLFontUnderlineValues.Single) myString.Append("text-decoration: underline;");
if (richText.FontName != "Arial") myString.Append("font-face: " + richText.FontName + ";");
if (richText.FontColor.Color.IsKnownColor) myString.Append("color: " + richText.FontColor.Color.Name + ";");
if (richText.FontSize != 10) myString.Append("font-size: " + richText.FontSize + ";");
myString.Append("'>"); // End the SPAN
if (richText.Text.Contains("http")) myString.Append("<a href='" + richText.Text + "'>");
myString.Append(richText.Text.Replace("\r\n", "<br>"));
if (richText.Text.Contains("http")) myString.Append("</a>");
myString.Append("</span>");
}
if (cell.HasHyperlink && cell.Hyperlink.IsExternal) myString.Append("</a>");
return myString.ToString();
}