2016-08-29 4 views
13

У меня есть этот код, который я знаю, что он работает быстроЭкспорт DataGridView в Excel со всеми форматом ячеек

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); })); 
} 

код прекрасно работает, но он делает копировать только значения является первенствовать, не скопируйте также формат ячеек (оберните текст, цвет обратной стороны, шрифт, границы и т. д.) Может ли кто-нибудь помочь мне на этом? Как заполнить этот код, есть точный формат, как в DataGridView?

+0

Вы проверили это: [? Как сохранить цвета при копировании-вставке из DataGridView, чтобы преуспеть] (HTTP : //stackoverflow.com/questions/9005721/how-to-keep-colors-when-copy-pasting-from-datagridview-to-excel), [Datagridview для Clipboard с форматированием] (http://stackoverflow.com/ вопросы/3829487/datagridview-to-clipboard-with-formatting)? Здесь также есть еще один: [Поддерживать формат DataGridView при экспорте в Excel (C#)] (https://social.msdn.microsoft.com/Forums/office/en-US/f615a10a-dcb9-440c-afb0-68d296cb0361/ поддерживать-DataGridView-формат, когда-экспортерах к excelc? форум = exceldev) – uTeisT

ответ

2

Суть вашего вопроса заключается в использовании буфера обмена в DataGridView, который не содержит форматирование ячеек. Поскольку буфер обмена не содержит форматирования, вы возвращаетесь к первоначальной проблеме медленной производительности, связанной с необходимостью устанавливать индивидуальные стили ячеек, которые используют Interop очень, очень медленно.

В этом случае будет лучше работать с файлами Excel с использованием XML вместо Interop. Ниже приведен метод, использующий 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"); 
    } 
} 
8

Я пытаюсь понять, почему это не дубликат. Есть examples по всей сети и here.

К моему удивлению & после большого количества исследований нет тщательных примеров Экспортного DataGridView в HTML или Excel с форматированием в любом месте в Интернете -до сих пор :)

Глядя на этом коде в вопрос, который вы обнаружили, насколько медленно он для копирования больших массивов данных с Interop и решили использовать буфер обмена вместо:

dataGridViewControl.SelectAll(); 
DataObject dataObj = dataGridViewControl.GetClipboardContent(); 
if (dataObj != null) 
    Invoke((Action)(() => { Clipboard.SetDataObject(dataObj); })); 

затруднение Тхи s вопрос - использование буфера обмена в DataGridView не содержит форматирование ячеек. Поскольку буфер обмена не содержит форматирования, вы возвращаетесь к первоначальной проблеме медленной производительности, связанной с необходимостью устанавливать индивидуальные стили ячеек, которые с использованием Interop очень и очень медленны.

В этом случае он может работать лучше для вашего проекта для создания файлов Excel с использованием XML вместо Interop. В то время как я впервые подумал, что это будет хорошим решением, и другой ответ здесь DartAlex демонстрирует это, я подумал, что буду комментировать ответ, который вы можете использовать с помощью метода Clipboard. Получение HTML Copy из DataGridViewс форматированием и вставляя, что в Excel:

DataGridView Для HTML таблицы с форматированием, а затем в Excel

enter image description here

//==================================================== 
//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); 
} 

TestData. csv:

Magic, Abra, Cadabra, Boom!
Coding, Fun, YeeHaa, ABS TableName
Привет, мир, Population.html, ТАБЛИЦА 1.
демография, 310102.xls, Comp.html, Таблица 2.

Я попытаюсь сделать этот код доступен в качестве проекта GitHub для других, чтобы расширить и усовершенствовать его и держать его в курсе с HTML и Exel версии.

0

Кажется, я нашел решение с использованием 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(); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^