我有这个代码,我知道它工作很快
CopyAlltoClipboard(dataGridViewControl);
Microsoft.Office.Interop.Excel.Application xlexcel;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlexcel = new Excel.Application();
xlexcel.Visible = true;
xlWorkBook = xlexcel.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheet.Name = page.Name;
Excel.Range CR = (Excel.Range)xlWorkSheet.Cells[1, 1];
CR.Select();
xlWorkSheet.PasteSpecial(CR, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, true);
((Microsoft.Office.Interop.Excel.Range)xlWorkSheet.Range["A1"]).EntireColumn.Delete(null); // delete the first column that has rows indexes
xlWorkBook.SaveAs(fileName);
private void CopyAlltoClipboard(DataGridView dataGridViewControl)
{
dataGridViewControl.SelectAll();
DataObject dataObj = dataGridViewControl.GetClipboardContent();
if (dataObj != null)
Invoke((Action)(() => { Clipboard.SetDataObject(dataObj); }));
}
代码工作正常,但它确实只复制 excel 的值,也不复制单元格格式(换行文本、背景色、字体、边框等) 谁能帮我解决这个问题?如何完成此代码,具有与数据网格视图中完全相同的格式?
好像是用interop和EPPlus找到了解决方案。我使用上面的代码只是为了复制Excel中的值,然后使用下面的代码(EPPlus代码)从dataGridView中获取格式。这段代码取决于您想从dataGridView中获取什么。在下面的代码中,我想从第一行获取WrapText,从每个书写的单元格中获取背景颜色
private void FinalizeWorkbook(DataTableReportParam reportParam, DataGridView dataGridViewControl)
{
FileInfo newFile = new FileInfo(reportParam.FileName);
ExcelPackage pck = new ExcelPackage(newFile);
IWorksheet worksheet = pck.Workbook.Worksheets[1];
// wrap text and color the crashes with problems (header)
for (int col = 1; col <= worksheet.Dimension.End.Column; col++)
{
worksheet[1, col].WrapText = true;
worksheet[1, col].AutofitRows();
if (String.Compare(dataGridViewControl[col - 1, 0].Style.BackColor.Name, "0") != 0)
worksheet[1, col].CellStyle.Color = dataGridViewControl[col - 1, 0].Style.BackColor;
}
// color the cells
for (int row = 2; row <= worksheet.Dimension.End.Row; row++)
{
for (int col = 1; col <= worksheet.Dimension.End.Column; col++)
{
if (String.Compare(dataGridViewControl[col - 1, row - 1].Style.BackColor.Name, "0") != 0)
worksheet[row, col].CellStyle.Color = dataGridViewControl[col - 1, row - 1].Style.BackColor;
}
}
//save and dispose
pck.Save();
pck.Dispose();
}
问题的关键是在DataGridView上使用不包含单元格格式的剪贴板。因为剪贴板不包含格式,所以你又回到了必须单独设置单元格样式的原始缓慢性能问题,使用互操作非常非常慢。
在这种情况下,使用XML而不是Interop创建Excel文件会更好。下面是一种使用ClosedXML将DataGridView导出到带有格式的Excel的方法。
using ClosedXML.Excel;
public void ExportToExcelWithFormatting(DataGridView dataGridView1)
{
string fileName;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "xls files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
saveFileDialog1.Title = "To Excel";
saveFileDialog1.FileName = this.Text + " (" + DateTime.Now.ToString("yyyy-MM-dd") + ")";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
fileName = saveFileDialog1.FileName;
var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add(this.Text);
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
worksheet.Cell(1, i + 1).Value = dataGridView1.Columns[i].Name;
}
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
worksheet.Cell(i + 2, j + 1).Value = dataGridView1.Rows[i].Cells[j].Value.ToString();
if (worksheet.Cell(i + 2, j + 1).Value.ToString().Length > 0)
{
XLAlignmentHorizontalValues align;
switch (dataGridView1.Rows[i].Cells[j].Style.Alignment)
{
case DataGridViewContentAlignment.BottomRight:
align = XLAlignmentHorizontalValues.Right;
break;
case DataGridViewContentAlignment.MiddleRight:
align = XLAlignmentHorizontalValues.Right;
break;
case DataGridViewContentAlignment.TopRight:
align = XLAlignmentHorizontalValues.Right;
break;
case DataGridViewContentAlignment.BottomCenter:
align = XLAlignmentHorizontalValues.Center;
break;
case DataGridViewContentAlignment.MiddleCenter:
align = XLAlignmentHorizontalValues.Center;
break;
case DataGridViewContentAlignment.TopCenter:
align = XLAlignmentHorizontalValues.Center;
break;
default:
align = XLAlignmentHorizontalValues.Left;
break;
}
worksheet.Cell(i + 2, j + 1).Style.Alignment.Horizontal = align;
XLColor xlColor = XLColor.FromColor(dataGridView1.Rows[i].Cells[j].Style.SelectionBackColor);
worksheet.Cell(i + 2, j + 1).AddConditionalFormat().WhenLessThan(1).Fill.SetBackgroundColor(xlColor);
worksheet.Cell(i + 2, j + 1).Style.Font.FontName = dataGridView1.Font.Name;
worksheet.Cell(i + 2, j + 1).Style.Font.FontSize = dataGridView1.Font.Size;
}
}
}
worksheet.Columns().AdjustToContents();
workbook.SaveAs(fileName);
//MessageBox.Show("Done");
}
}
更新:现在可在GitHub:https://github.com/MeaningOfLights/DataGridToHTML
我很难理解为什么这不是复制品。网上和这里都有例子。
令我惊讶的是
查看您问题中的这段代码,您会发现使用Interop复制大型数据集有多慢,并选择使用剪贴板:
dataGridViewControl.SelectAll();
DataObject dataObj = dataGridViewControl.GetClipboardContent();
if (dataObj != null)
Invoke((Action)(() => { Clipboard.SetDataObject(dataObj); }));
这个问题的关键是——在DataGridView上使用剪贴板不包含单元格格式。因为剪贴板不包含格式,你又回到了原来的缓慢的性能问题,必须单独设置单元格样式,使用Interop是非常非常慢的。
在这种情况下,使用XML而不是Interop创建Excel文件可能会更好。所以,当我第一次认为这是一个很好的解决方法,而DartAalex的另一个答案证明了这一点时,我想我应该编写一个可以与剪贴板方法一起使用的答案。获取带有格式的DataGridView的HTML副本并将其粘贴到Excel中:
DataGridView通过格式化超文本标记语言表,然后进入Excel
//====================================================
//DataGridView Export To HTML by Jeremy Thompson: https://stackoverflow.com/questions/39210329/
//====================================================
public string ConvertDataGridViewToHTMLWithFormatting(DataGridView dgv)
{
StringBuilder sb = new StringBuilder();
//create html & table
sb.AppendLine("<html><body><center><table border='1' cellpadding='0' cellspacing='0'>");
sb.AppendLine("<tr>");
//create table header
for (int i = 0; i < dgv.Columns.Count; i++)
{
sb.Append(DGVHeaderCellToHTMLWithFormatting(dgv, i));
sb.Append(DGVCellFontAndValueToHTML(dgv.Columns[i].HeaderText, dgv.Columns[i].HeaderCell.Style.Font));
sb.AppendLine("</td>");
}
sb.AppendLine("</tr>");
//create table body
for (int rowIndex = 0; rowIndex < dgv.Rows.Count; rowIndex++)
{
sb.AppendLine("<tr>");
foreach (DataGridViewCell dgvc in dgv.Rows[rowIndex].Cells)
{
sb.AppendLine(DGVCellToHTMLWithFormatting(dgv, rowIndex, dgvc.ColumnIndex));
string cellValue = dgvc.Value == null ? string.Empty : dgvc.Value.ToString();
sb.AppendLine(DGVCellFontAndValueToHTML(cellValue, dgvc.Style.Font));
sb.AppendLine("</td>");
}
sb.AppendLine("</tr>");
}
//table footer & end of html file
sb.AppendLine("</table></center></body></html>");
return sb.ToString();
}
//TODO: Add more cell styles described here: https://msdn.microsoft.com/en-us/library/1yef90x0(v=vs.110).aspx
public string DGVHeaderCellToHTMLWithFormatting(DataGridView dgv, int col)
{
StringBuilder sb = new StringBuilder();
sb.Append("<td");
sb.Append(DGVCellColorToHTML(dgv.Columns[col].HeaderCell.Style.ForeColor, dgv.Columns[col].HeaderCell.Style.BackColor));
sb.Append(DGVCellAlignmentToHTML(dgv.Columns[col].HeaderCell.Style.Alignment));
sb.Append(">");
return sb.ToString();
}
public string DGVCellToHTMLWithFormatting(DataGridView dgv, int row, int col)
{
StringBuilder sb = new StringBuilder();
sb.Append("<td");
sb.Append(DGVCellColorToHTML(dgv.Rows[row].Cells[col].Style.ForeColor, dgv.Rows[row].Cells[col].Style.BackColor));
sb.Append(DGVCellAlignmentToHTML(dgv.Rows[row].Cells[col].Style.Alignment));
sb.Append(">");
return sb.ToString();
}
public string DGVCellColorToHTML(Color foreColor, Color backColor)
{
if (foreColor.Name == "0" && backColor.Name == "0") return string.Empty;
StringBuilder sb = new StringBuilder();
sb.Append(" style=\"");
if (foreColor.Name != "0" && backColor.Name != "0")
{
sb.Append("color:#");
sb.Append(foreColor.R.ToString("X2") + foreColor.G.ToString("X2") + foreColor.B.ToString("X2"));
sb.Append("; background-color:#");
sb.Append(backColor.R.ToString("X2") + backColor.G.ToString("X2") + backColor.B.ToString("X2"));
}
else if (foreColor.Name != "0" && backColor.Name == "0")
{
sb.Append("color:#");
sb.Append(foreColor.R.ToString("X2") + foreColor.G.ToString("X2") + foreColor.B.ToString("X2"));
}
else //if (foreColor.Name == "0" && backColor.Name != "0")
{
sb.Append("background-color:#");
sb.Append(backColor.R.ToString("X2") + backColor.G.ToString("X2") + backColor.B.ToString("X2"));
}
sb.Append(";\"");
return sb.ToString();
}
public string DGVCellFontAndValueToHTML(string value,Font font)
{
//If no font has been set then assume its the default as someone would be expected in HTML or Excel
if (font == null || font == this.Font && !(font.Bold | font.Italic | font.Underline | font.Strikeout)) return value;
StringBuilder sb = new StringBuilder();
sb.Append(" ");
if (font.Bold) sb.Append("<b>");
if (font.Italic) sb.Append("<i>");
if (font.Strikeout) sb.Append("<strike>");
//The <u> element was deprecated in HTML 4.01. The new HTML 5 tag is: text-decoration: underline
if (font.Underline) sb.Append("<u>");
string size = string.Empty;
if (font.Size != this.Font.Size) size = "font-size: " + font.Size + "pt;";
//The <font> tag is not supported in HTML5. Use CSS or a span instead.
if (font.FontFamily.Name != this.Font.Name)
{
sb.Append("<span style=\"font-family: ");
sb.Append(font.FontFamily.Name);
sb.Append("; ");
sb.Append(size);
sb.Append("\">");
}
sb.Append(value);
if (font.FontFamily.Name != this.Font.Name) sb.Append("</span>");
if (font.Underline) sb.Append("</u>");
if (font.Strikeout) sb.Append("</strike>");
if (font.Italic) sb.Append("</i>");
if (font.Bold) sb.Append("</b>");
return sb.ToString();
}
public string DGVCellAlignmentToHTML(DataGridViewContentAlignment align)
{
if (align == DataGridViewContentAlignment.NotSet) return string.Empty;
string horizontalAlignment = string.Empty;
string verticalAlignment = string.Empty;
CellAlignment(align, ref horizontalAlignment, ref verticalAlignment);
StringBuilder sb = new StringBuilder();
sb.Append(" align='");
sb.Append(horizontalAlignment);
sb.Append("' valign='");
sb.Append(verticalAlignment);
sb.Append("'");
return sb.ToString();
}
private void CellAlignment(DataGridViewContentAlignment align, ref string horizontalAlignment, ref string verticalAlignment)
{
switch (align)
{
case DataGridViewContentAlignment.MiddleRight:
horizontalAlignment = "right";
verticalAlignment = "middle";
break;
case DataGridViewContentAlignment.MiddleLeft:
horizontalAlignment = "left";
verticalAlignment = "middle";
break;
case DataGridViewContentAlignment.MiddleCenter:
horizontalAlignment = "centre";
verticalAlignment = "middle";
break;
case DataGridViewContentAlignment.TopCenter:
horizontalAlignment = "centre";
verticalAlignment = "top";
break;
case DataGridViewContentAlignment.BottomCenter:
horizontalAlignment = "centre";
verticalAlignment = "bottom";
break;
case DataGridViewContentAlignment.TopLeft:
horizontalAlignment = "left";
verticalAlignment = "top";
break;
case DataGridViewContentAlignment.BottomLeft:
horizontalAlignment = "left";
verticalAlignment = "bottom";
break;
case DataGridViewContentAlignment.TopRight:
horizontalAlignment = "right";
verticalAlignment = "top";
break;
case DataGridViewContentAlignment.BottomRight:
horizontalAlignment = "right";
verticalAlignment = "bottom";
break;
default: //DataGridViewContentAlignment.NotSet
horizontalAlignment = "left";
verticalAlignment = "middle";
break;
}
}
//Easy repro - copy/paste all this code in a Winform app!
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string configFile = System.IO.Path.Combine(Application.StartupPath.Replace("\\bin\\Debug", ""), "testData.csv");
List<string[]> rows = System.IO.File.ReadAllLines(configFile).Select(x => x.Split(',')).ToList();
DataTable dataTable = new DataTable();
dataTable.Columns.Add("testing");
dataTable.Columns.Add("one");
dataTable.Columns.Add("two");
dataTable.Columns.Add("three");
rows.ForEach(x => { dataTable.Rows.Add(x); });
this.dgv.DataSource = dataTable;
dgv.Columns[0].HeaderCell.Style.Font = new Font(this.Font, FontStyle.Strikeout);
dgv[0, 0].Style.BackColor = Color.Aqua;
dgv[1, 0].Style.Alignment = DataGridViewContentAlignment.BottomRight;
dgv[2, 0].Style.Font = new Font(new FontFamily("Calibri"),(float)16);
dgv[3, 0].Style.ForeColor = Color.Red;
dgv[0, 1].Style.Font = new Font(this.Font, FontStyle.Bold);
dgv[1, 1].Style.Font = new Font(this.Font, FontStyle.Underline);
dgv[2, 1].Style.Font = new Font(this.Font, FontStyle.Italic);
dgv[3, 1].Style.Font = new Font(this.Font, FontStyle.Bold | FontStyle.Underline);
dgv[3, 1].Style.ForeColor = Color.Green;
dgv[3, 1].Style.BackColor = Color.Yellow;
dgv[0, 2].Style.Font = new Font(new FontFamily("Times New Roman"), (float)18);
dgv[1, 2].Style.Font = new Font(new FontFamily("Georgia"), (float)12);
dgv[2, 2].Style.Font = new Font(new FontFamily("Arial"), (float)14);
dgv[3, 2].Style.Font = new Font(new FontFamily("Verdana"), (float)18);
dgv[0, 3].Style.Font = new Font(new FontFamily("Courier New"), (float)11);
dgv[1, 3].Style.Font = new Font(new FontFamily("Lucida Console"), (float)18);
dgv[2, 3].Style.Font = new Font(new FontFamily("Times"), (float)14);
dgv[3, 3].Style.Font = new Font(new FontFamily("serif"), (float)12);
}
private void button1_Click(object sender, EventArgs e)
{
string dgvToHTMLTable = ConvertDataGridViewToHTMLWithFormatting(dgv);
Clipboard.SetText(dgvToHTMLTable);
}
测试数据.csv:
魔法,阿布拉,卡达布拉,轰
Coding,Fun,YeeHaa,ABS TableName
你好,世界,Population.html,表1。
人口统计,310102.xls,Comp.html,表2。
当我将公式添加到google工作表时,它们工作正常,但当我添加新行时,公式不会被复制。为了克服这个问题,我找到了公式数组。这适用于简单的应用,例如在单元格D4中,添加了以下公式 然而,当公式变得更复杂一点时,它就崩溃了。 这仍然是一个非常简单的公式,似乎打破了,而我的工作表中的公式通常更棘手,例如 它读取单元格Y5的数据(这是我手动输入的时区的名称),并查找另一张名为“世界时钟”的表,其中包含这些
我们有一个内部的遗留java库,可以用jasper spring生成报告,并将它们导出为html、pdf或xls。然而,excel文件的所有单元格都具有相同的格式(没有),我们有一个报告,其中一列填充了文本,有人担心它会被解释为带有数值的公式或其他类型的代码。同样,我们有应该出现在报告中的带有前导零的字符串。我试过设置JExcelApiExporterParameter。通过jasperExpor
我正在创建一个新的PDF,其中将包含其他文档的汇编。 这些其他文档可以是word/excel/图像/PDF。 我希望将所有这些内容添加到表中的单元格中,该单元格被添加到文档中-这给了我自动添加页面的好处,将元素定位在单元格中而不是页面中,并允许我更轻松地将内容保持在与我提供的相同的顺序(如img,doc,pdf,img,pdf等) 向表中添加图像非常简单。 我正在将word/excel文档转换为P
背景: 在项目开发中,经常需要下载模板/导出表单数据(excel)格式的需求,虽然xlsx库可以满足基本需求,但是有些excel表的样式很难定制化,所以想着自己封装一个 尝试: 封装思路: excel和table关联起来,而连接两者的桥梁为new Blob()构造函数,示例代码如下: 结果: 可以正常生成excel文件 缺点: 但是又有点不太像excel的格式,比如我想在excel表里面新增行或者
null 如您所料,A3将导致。现在将A2的格式更改为会计,使用小数点后2位。A2现在读,但是基础值仍然是,所以A3仍然是。 VBA 制作一个新模块并添加以下函数: null 和具有相同的基础值,但和没有,尽管它们都是使用和的方法计算的。 ()中的表达式正在访问和的实际基础值。如何在VBA中访问这些值?
这是我第一次在这里发帖,所以请直接回答我的问题,我会尽我所能解释我的问题。 我的工作簿中有两个工作表,其中工作表1直观地表示一个有162个方格的托盘中多个单位(A1到A162)的位置。并不是所有的方格都被填满,因为有些方格是空的。 现在,第2页显示了单位A1到A162的数值。我已经使用条件格式为每个值分配颜色。 我试图从sheet2将A1的颜色复制到sheet1中具有A1值的单元格,但没有成功。
问题内容: 我正在处理生成Excel文件的JasperReport报告。由于某种原因,我的单元格格式/类型不应该如此。例如,我的单元格中有Date对象,但是当我生成Excel文件时,它将单元格类型设置为Number,或者Long类型是单元格中的文本,但是单元格的格式是number,并且当用户编辑日期单元格时(例如,日期为11/02) / 2012更改为11/03/2012),它将日期转换为数字(4
我的程序(C#.NET4.5)必须能够生成一些可以加载到Excel中的报告。我选择将报表导出为。csv格式,因为这是导出为excel理解的格式的最简单的方法。并且它不要求Excel安装在运行我的程序的机器上。 我的问题是导出日期。