一.前言
最近做的項目中,需要實作如下功能:在Winform中,将DataGridView中的資料導出到某個Excel檔案,以及讀取某個存在的Excel檔案的内容,并更新資料庫。
為了實作這些功能,選擇去用Com元件。
像下面這種表:
點選右上角的 導出Excel 按鈕,出現彈窗選擇存儲路徑:
取好檔案名點确定,就能在該路徑下儲存一個xlsx檔案,打開檔案後效果如下:
可以看到,程式界面DataGridView中的内容完整地導入了xlsx檔案,并且單元格合并、字元居中顯示都已實作。
Excel表格的導入操作流程和上面相同,點選按鈕選取路徑下的一個檔案。這裡就不截圖了。
二.解決思路
導出:
1 SaveFileDialog saveDialog = new SaveFileDialog(); 來創造彈窗,擷取選擇的檔案名。
2 在右邊資料總管中,解決方案——引用——添加引用——程式集(擴充)中找到Microsoft.Office.Interop.Excel——确定
在命名空間中加上:using Excel = Microsoft.Office.Interop.Excel;
3 建立Excel對象,建立虛表
Application 相當于建立一個Excel程式,想象成電腦上打開了Excel程式
Workbooks 是application的一個屬性,是目前EXCEL程序打開的所有工作簿數組,使用workbooks[1]、workbooks[2]可以通路他們。
Workbook 是類型,是工作簿,一個EXCEL檔案(包含多個工作表)就是一個工作簿
worksheet 是裡面包含的表,你在桌面右鍵建立個excel,預設裡面就有3個sheet,sheet1,sheet2,sheet3.就這個意思。
4 根據實際情況對虛表進行寫資料。可以參考下面的代碼。
5 複制虛表,儲存檔案,關閉Application,銷毀資源。
導入:
導入的前兩點和導出相同,第3點開始有差別。
1,2 ,5 同導出
3 workbook打開檔案,worksheet擷取b表格
4 讀取Worksheet指定行列的資料。可以參考下面的代碼。
Cell [ 行 , 列 ] ,往裡面填行列來指定某個單元格。
注:需加(Excel.Range)進行強轉,否則無法讀到單元格的。
三.流程代碼
導出Excel方法,傳入DataGridView作為參數
private void ExportExcel(object sender, EventArgs e,DataGridView myGrid)
{
string fileName = "";
string saveFileName = "";
SaveFileDialog saveDialog = new SaveFileDialog();
saveDialog.DefaultExt = "xlsx";
saveDialog.Filter = "Excel檔案|*.xlsx";
saveDialog.FileName = fileName;
saveDialog.ShowDialog();
saveFileName = saveDialog.FileName;
if (saveFileName.IndexOf(":") < 0) return; //被點了取消
Microsoft.Office.Interop.Excel.Application xlApp =
new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
MessageBox.Show("無法建立Excel對象,您的電腦可能未安裝Excel");
return;
}
Microsoft.Office.Interop.Excel.Range range;
Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks;
Microsoft.Office.Interop.Excel.Workbook workbook =
workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
Microsoft.Office.Interop.Excel.Worksheet worksheet =
(Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1];//取得sheet1
//寫入标題
for (int i = 0; i < myGrid.ColumnCount; i++)
{ worksheet.Cells[1, i + 1] = myGrid.Columns[i].HeaderText; }
//寫入數值
for (int r = 0; r < myGrid.Rows.Count; r++)
{
for (int i = 0; i < myGrid.ColumnCount; i++)
{
worksheet.Cells[r + 2, i + 1] = myGrid.Rows[r].Cells[i].Value;
}
System.Windows.Forms.Application.DoEvents();
}
worksheet.Columns.EntireColumn.AutoFit();//列寬自适應
xlApp.Cells.HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter; //全局居中對齊
xlApp.DisplayAlerts = false;
int sum = 2;
for (int i = 0; i < sql.RootCount.Count; i++)
{
int temp = sql.RootCount[i];
if (temp > 1)
{
/*合并單元格*/
range = worksheet.get_Range("A" + sum.ToString(), "A" + (sum + temp - 1).ToString());
range.Merge(false);
range = worksheet.get_Range("B" + sum.ToString(), "B" + (sum + temp - 1).ToString());
range.Merge(false);
sum += temp;
}
else
sum++;
}
MessageBox.Show(fileName + "資料儲存成功", "提示", MessageBoxButtons.OK);
if (saveFileName != "")
{
try
{
workbook.Saved = true;
workbook.SaveCopyAs(saveFileName); //fileSaved = true;
}
catch (Exception ex)
{//fileSaved = false;
MessageBox.Show("導出檔案時出錯,檔案可能正被打開!\n" + ex.Message);
}
}
xlApp.Quit();
GC.Collect();//強行銷毀
}
導入Excel方法,我這裡是結合資料庫更新。可以根據需要處理讀到的資料。
private void ImportExcel(object sender, EventArgs e)
{
string fileName = "";
string openFileName = "";
OpenFileDialog openDialog = new OpenFileDialog();
openDialog.DefaultExt = "xlsx";
openDialog.Filter = "Excel檔案|*.xlsx";
openDialog.FileName = fileName;
openDialog.ShowDialog();
openFileName = openDialog.FileName;
if (openFileName.IndexOf(":") < 0) return; //被點了取消
if (MessageBox.Show("導入Excel會清除原資料庫中的所有内容!是否繼續?", "注意", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
{
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
if (xlApp == null)
{
MessageBox.Show("無法建立Excel對象,您的電腦可能未安裝Excel");
return;
}
object missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Excel.Workbooks workbook = xlApp.Workbooks;
workbook.Open(openFileName, missing, true, missing, missing, missing,
missing, missing, missing, true, missing, missing, missing, missing, missing);
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)xlApp.Worksheets.get_Item(1);
int rows = worksheet.UsedRange.Rows.Count;
int columns = worksheet.UsedRange.Columns.Count;
if(columns != 5)
{
MessageBox.Show("Excel内容格式不正确,請導入正确格式的表格");
return;
}
string TableName = worksheet.Name;
MainTable.sql.ClearDatabase();
for (int i = 2; i < rows+1; i++)
{
string name = Convert.ToString(((Excel.Range)worksheet.Cells[i,1]).Value2);
string score = Convert.ToString(((Excel.Range)worksheet.Cells[i,2]).Value2);
if(name != null)
{
MainTable.sql.ImportExcelData(name, score, null, null);
}
}
for (int j = 2; j < rows + 1; j++)
{
string name = Convert.ToString(((Excel.Range)worksheet.Cells[ j , 3 ]).Value2);
string score = Convert.ToString(((Excel.Range)worksheet.Cells[ j , 4 ]).Value2);
string detail = Convert.ToString(((Excel.Range)worksheet.Cells[j, 5]).Value2);
string upname = null;
int i = 0;
while ( upname == null)
{
upname = Convert.ToString(((Excel.Range)worksheet.Cells[j - i, 1]).Value2);
i++;
}
if (name != null)
{
MainTable.sql.ImportExcelData(name, score, detail,upname);
}
}
MessageBox.Show("導入完成!");
xlApp.Quit();
GC.Collect();//強行銷毀
}
else
{
return;
}
}
四.補充說明
1. Excel單元格合并
以圖檔為例,若想合并A2-A4單元格的内容,運作如下代碼:
range = worksheet.get_Range("A2" "A4" )); //範圍選擇:A1-A4
range.Merge(false); //按預設設定合并
2. 單元格居中
xlApp.Cells.HorizontalAlignment = Microsoft.Office.Interop.Excel.Constants.xlCenter; //全局居中對齊
3. 單元格合并後,運作會彈出Excel提示:合并單元格時,僅保留左上角單元格的值,而放棄其他值。
合并一行就會彈一次,很煩,不想讓它顯示。運作下面代碼解決:
xlApp.DisplayAlerts = false; //關閉程式的提醒