using System; using System.Collections; using System.Windows.Forms; using System.IO; using System.Reflection; using System.Runtime.InteropServices; class ExcelLateBind { private object oApp; private object oBook; private object oBooks; private object oSheet; private object oSheetCount; private object oSheets; private object oRange; private object oLastCell; private object oCells; private object oCell; private object oValue; private object[] Params; private string FilePath; public string OpenFile { get; private set; } public bool IsOpen { get; private set; } public bool IsSelectSheet { get; private set; } public int SheetCount { get; private set; } public int OpenPageNo { get; private set; } public int MaxCol { get; private set; } public int MaxRow { get; private set; } private bool MessageShow; public string ErrorMessage { get; private set; } //コンストラクタ public ExcelFileControl(string ExcelFilePath, bool ShowMessageBox) { FilePath = ExcelFilePath; IsOpen = false; IsSelectSheet = false; MessageShow = ShowMessageBox; ErrorMessage = ""; Type oClassType; oClassType = Type.GetTypeFromProgID("Excel.Application"); oApp = Activator.CreateInstance(oClassType); oBooks = oApp.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oApp, null); } //デストラクタ ~ExcelFileControl() { Release(); GC.Collect(); } /// /// 指定されたファイルを開きます /// /// public bool Open() { bool ret = false; if (File.Exists(Path.GetDirectoryName(FilePath) + "\\~$" + Path.GetFileName(FilePath))) { MessageBox.Show("別プロセスでファイルを使用中のため開くことが出来ません。", "既にファイルが開かれています。", MessageBoxButtons.OK, MessageBoxIcon.Information); Close(false); return ret; } try { Params = new object[15]; Params[0] = FilePath; for (int i = 1; i < Params.Length; i++) Params[i] = Type.Missing; ReleaseObject(oSheetCount); ReleaseObject(oSheets); ReleaseObject(oBook); if (File.Exists(FilePath)) oBook = oBooks.GetType().InvokeMember("Open", BindingFlags.GetProperty, null, oBooks, Params); else oBook = oBooks.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, oBooks, null); oSheets = oBook.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty, null, oBook, null); oSheetCount = oSheets.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, oSheets, null); SheetCount = (int)oSheetCount; OpenFile = FilePath; ret = true; } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("ファイルを開くのに失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:FileOpen)", MessageBoxButtons.OK, MessageBoxIcon.Error); } IsOpen = ret; return ret; } /// /// 最後に1枚シートを追加して、追加したシートを選択します /// /// public bool AddSheet() { bool ret = false; if (!IsOpen) { ErrorMessage = "ファイルを開いてからシートの選択を実行してください。"; if (MessageShow) MessageBox.Show(ErrorMessage, "シート追加エラー (IsOpen = false)"); return ret; } try { ReleaseObject(oSheetCount); ReleaseObject(oSheets); oSheets = oBook.GetType().InvokeMember("Worksheets", BindingFlags.GetProperty, null, oBook, null); oSheetCount = oSheets.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, oSheets, null); SheetCount = (int)oSheetCount; SelectSheet(SheetCount); Params = new object[4]; Params[0] = Type.Missing; Params[1] = oSheet; Params[2] = 1; Params[3] = Type.Missing; ReleaseObject(oSheetCount); oSheet = oSheets.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, oSheets, Params); oSheetCount = oSheets.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, oSheets, null); SheetCount = (int)oSheetCount; IsSelectSheet = true; OpenPageNo = SheetCount; OpenFile = FilePath; ret = true; } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("シートの追加に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:AddSheet)", MessageBoxButtons.OK, MessageBoxIcon.Error); } IsOpen = ret; return ret; } /// /// 最後に1枚シートを追加して、追加したシートを選択します /// /// 追加するシートの名前を指定します /// public bool AddSheet(string SheetName) { bool ret = false; try { if (AddSheet()) { Params = new object[1]; Params[0] = SheetName; oSheet.GetType().InvokeMember("Name", BindingFlags.SetProperty, null, oSheet, Params); ret = true; } } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("シートの追加に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:AddSheet[string SheetName = \"" + SheetName + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); } IsOpen = ret; return ret; } /// /// エクセルのシートを選択します /// /// シート名を指定 public void SelectSheet(string SheetName) { if (!IsOpen) { ErrorMessage = "ファイルを開いてからシートの選択を実行してください。"; if (MessageShow) MessageBox.Show(ErrorMessage, "シート選択エラー (IsOpen = false)"); return; } object Name; int SheetNo = 0; int lp = 0; try { foreach (object sheet in (IEnumerable)oSheets) { lp++; Name = sheet.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, sheet, null); if (SheetName == Name.ToString()) { SheetNo = lp; break; } } } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("シートの選択に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:SelectSheet[string SheetName = \"" + SheetName + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (SheetNo == 0) { ErrorMessage = "指定されたシート名を見つけることが出来ませんでした。"; if (MessageShow) MessageBox.Show(ErrorMessage, "シート選択エラー (SheetNo = 0)"); return; } SelectSheet(SheetNo); } /// /// エクセルのシートを選択します /// /// シート番号を指定 public void SelectSheet(int SheetNo) { if (!IsOpen) { ErrorMessage = "ファイルを開いてからシートの選択を実行してください。"; if (MessageShow) MessageBox.Show(ErrorMessage, "シート選択エラー (IsOpen = false)"); return; } try { Params = new object[1]; Params[0] = SheetNo; OpenPageNo = SheetNo; ReleaseObject(oLastCell); ReleaseObject(oCells); ReleaseObject(oSheet); oSheet = oSheets.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, oSheets, Params); oCells = oSheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty, null, oSheet, null); Params = new object[2]; Params[0] = 11; Params[1] = Type.Missing; oLastCell = oCells.GetType().InvokeMember("SpecialCells", BindingFlags.InvokeMethod, null, oCells, Params); MaxCol = (int)oLastCell.GetType().InvokeMember("Column", BindingFlags.GetProperty, null, oLastCell, null); MaxRow = (int)oLastCell.GetType().InvokeMember("Row", BindingFlags.GetProperty, null, oLastCell, null); IsSelectSheet = true; } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("シートの選択に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:SelectSheet[int SheetNo = \"" + SheetNo.ToString() + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } /// /// セルの値を取得します /// /// Cellを指定(例:B5) /// public string GetValue(string Cell) { string ret = ""; int col = 0; int row = 0; CellStringToColAndRow(Cell, ref col, ref row); ret = GetValue(col, row); return ret; } /// /// セルの値を取得します /// /// 列文字を指定 /// 行番号を指定 /// public string GetValue(string col, int row) { string ret = ""; ret = GetValue(ColStringToColNumber(col), row); return ret; } /// /// セルの値を取得します /// /// 列番号を指定 /// 行番号を指定 /// public string GetValue(int col, int row) { string ret = ""; if (!IsSelectSheet) { ErrorMessage = "シートの指定がされていません。"; if (MessageShow) MessageBox.Show(ErrorMessage, "値取得エラー (IsSelectSheet = false)"); return null; } try { Params = new object[2]; Params[0] = row; Params[1] = col; oCell = oCells.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, oCells, Params); oValue = oCell.GetType().InvokeMember("Text", BindingFlags.GetProperty, null, oCell, null); ReleaseObject(oValue); ReleaseObject(oCell); ret = oValue.ToString(); } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("値の取得に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:GetValue[int col = \"" + col.ToString() + "\", int row = \"" + row.ToString() + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); return null; } return ret; } //IsNumeric関数の代用 /// /// 数値として扱える文字列かどうかを判定します /// /// 判断したい文字列 /// 数値として扱える場合:true private bool IsNum(string strText) { double d; if (double.TryParse(strText, System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.CurrentInfo, out d) == true) return true; else return false; } //列の文字列から列番号を判定する private int ColStringToColNumber(string col) { int ret = 0; for (int i = 0; i < col.Length; i++) { ret += Convert.ToInt32(Convert.ToChar(col.Substring(i, 1).ToUpper())) - 64; if (i != 0) ret += 26; } return ret; } //Cellの指定文字列を行と列に分割 private void CellStringToColAndRow(string Cell, ref int col, ref int row) { for (int i = 1; i <= Cell.Length; i++) if (!IsNum(Cell.Substring(Cell.Length - i, 1))) { col = ColStringToColNumber(Cell.Substring(0, Cell.Length - i + 1)); row = int.Parse(Cell.Substring(Cell.Length - i + 1)); break; } } /// /// セルに値をセットします /// /// Cellを指定(例:B5) /// セットしたい文字列を指定 public void SetValue(string Cell, string value) { if (!IsSelectSheet) { ErrorMessage = "シートの指定がされていません。"; if (MessageShow) MessageBox.Show(ErrorMessage, "値セットエラー (IsSelectSheet = false)"); return; } try { Params = new object[2]; Params[0] = Cell; Params[1] = Missing.Value; oRange = oSheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, oSheet, Params); Params = new object[1]; Params[0] = value; oRange.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, oRange, Params); ReleaseObject(oRange); } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("値の設定に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:SetValue[Cell = \"" + Cell + "\", value = \"" + value + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// セルに値をセットします /// /// 列文字を指定 /// 行番号を指定 /// セットしたい文字列を指定 public void SetValue(string col, int row, string value) { SetValue(col + row.ToString(), value); } /// /// セルに値をセットします /// /// 列番号を指定 /// 行番号を指定 /// セットしたい文字列を指定 public void SetValue(int col, int row, string value) { SetValue(ColNumberToColString(col) + row, value); } //列の番号から列文字を判定する とりあえず文字列3桁まで対応 private string ColNumberToColString(int col) { string ret = ""; int iChar = 0; int add = 0; iChar = col / (int)Math.Pow(26, 2); if (iChar != 0) { col -= iChar * (int)Math.Pow(26, 2); ret += Convert.ToChar(iChar + 64).ToString(); iChar = 0; add = 1; } iChar = col / 26; if (iChar != 0 && col > 26) { if (col % 26 == 0) iChar--; col -= iChar * 26; ret += Convert.ToChar(iChar + 64).ToString(); iChar = 0; } iChar = col; ret += Convert.ToChar(iChar + 64 + add).ToString(); return ret; } /// /// 範囲を指定して、全体(中セルも含めて)に罫線を描きます /// /// 開始セルを指定します /// 終了セルを指定します /// 線のスタイルを設定します(XlLineStyleクラスで定義されている値を使用できます) /// 線の太さを設定します(XlLineWeightクラスで定義されている値を使用できます) public void SetBorderLine(string StartCell, string EndCell, XlLineStyle LineStyle, XlLineWeight LineWeight) { if (!IsSelectSheet) { ErrorMessage = "シートの指定がされていません。"; if (MessageShow) MessageBox.Show(ErrorMessage, "罫線描画エラー (IsSelectSheet = false)"); return; } object oBorders = null; object[] oLineStyle = new object[1]; object[] oLineWeight = new object[1]; ReleaseObject(oRange); oLineStyle[0] = LineStyle; oLineWeight[0] = LineWeight; try { Params = new object[1]; Params[0] = StartCell + ":" + EndCell; oRange = oSheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, oSheet, Params); oBorders = oRange.GetType().InvokeMember("Borders", BindingFlags.GetProperty, null, oRange, null); oBorders.GetType().InvokeMember("LineStyle", BindingFlags.SetProperty, null, oBorders, oLineStyle); if (LineStyle != XlLineStyle.None && LineStyle != XlLineStyle.Double) oBorders.GetType().InvokeMember("Weight", BindingFlags.SetProperty, null, oBorders, oLineWeight); } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("罫線の描画に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:SetBorderLine[StartCell = \"" + StartCell + "\", EndCell = \"" + EndCell + "\", LineStyle = \"" + LineStyle.ToString() + "\", LineWeight = \"" + LineWeight.ToString() + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); } ReleaseObject(oBorders); } /// /// 範囲を指定して、全体(中セルも含めて)に罫線を描きます /// /// 開始セルを指定します /// 終了セルを指定します /// セルのどの位置に罫線を描くかを設定します(XlDrawLineで定義されている値を使用できます) /// 線のスタイルを設定します(XlLineStyleクラスで定義されている値を使用できます) /// 線の太さを設定します(XlLineWeightクラスで定義されている値を使用できます) public void SetBorderLine(string StartCell, string EndCell, XlDrawLine BorderLinePosition, XlLineStyle LineStyle, XlLineWeight LineWeight) { if (!IsSelectSheet) { ErrorMessage = "シートの指定がされていません。"; if (MessageShow) MessageBox.Show(ErrorMessage, "罫線描画エラー (IsSelectSheet = false)"); return; } object oBorders = null; object oBorder = null; object[] oLineStyle = new object[1]; object[] oLineWeight = new object[1]; object[] oBorderLinePos = new object[1]; ReleaseObject(oRange); oLineStyle[0] = LineStyle; oLineWeight[0] = LineWeight; oBorderLinePos[0] = BorderLinePosition; try { Params = new object[1]; Params[0] = StartCell + ":" + EndCell; oRange = oSheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, oSheet, Params); oBorders = oRange.GetType().InvokeMember("Borders", BindingFlags.GetProperty, null, oRange, null); oBorder = oBorders.GetType().InvokeMember("_Default", BindingFlags.GetProperty, null, oBorders, oBorderLinePos); oBorder.GetType().InvokeMember("LineStyle", BindingFlags.SetProperty, null, oBorder, oLineStyle); if (LineStyle != XlLineStyle.None && LineStyle != XlLineStyle.Double) oBorder.GetType().InvokeMember("Weight", BindingFlags.SetProperty, null, oBorder, oLineWeight); } catch (Exception ex) { ErrorMessage = ex.ToString(); if (MessageShow) MessageBox.Show("罫線の描画に失敗しました。" + Environment.NewLine + Environment.NewLine + "エラーの詳細は以下の通りです。" + Environment.NewLine + "エラー発生個所:" + ex.Source + Environment.NewLine + "エラー内容:" + ErrorMessage, "例外エラー発生 (ExcelFileControl:SetBorderLine[StartCell = \"" + StartCell + "\", EndCell = \"" + EndCell + "\", BorderLinePosition = \"" + BorderLinePosition + "\" LineStyle = \"" + LineStyle.ToString() + "\", LineWeight = \"" + LineWeight.ToString() + "\"])", MessageBoxButtons.OK, MessageBoxIcon.Error); } ReleaseObject(oBorder); ReleaseObject(oBorders); } /// /// Excelファイルを閉じます /// /// 保存するかどうかを設定します public void Close(bool save) { Params = new object[1]; Params[0] = false; oApp.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oApp, Params); oApp.GetType().InvokeMember("DisplayAlerts", BindingFlags.SetProperty, null, oApp, Params); oApp.GetType().InvokeMember("UserControl", BindingFlags.SetProperty, null, oApp, Params); Params = new object[2]; Params[0] = save; Params[1] = FilePath; oBook.GetType().InvokeMember("Close", BindingFlags.InvokeMethod, null, oBook, Params); //BookのClose oBooks.GetType().InvokeMember("Close", BindingFlags.InvokeMethod, null, oBooks, null); //BooksのClose oApp.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, oApp, null); //ApplicationのClose IsSelectSheet = false; IsOpen = false; Release(); GC.Collect(); } private void ReleaseObject(object o) { if (o != null) if (Marshal.IsComObject(o)) { Marshal.ReleaseComObject(o); o = null; } } private void Release() { ReleaseObject(oValue); ReleaseObject(oCell); ReleaseObject(oCells); ReleaseObject(oLastCell); ReleaseObject(oRange); ReleaseObject(oSheet); ReleaseObject(oSheetCount); ReleaseObject(oSheets); ReleaseObject(oBook); ReleaseObject(oBooks); ReleaseObject(oApp); } //罫線のStyle public enum XlLineStyle : int { Normal = 1, Dash = -4115, DashDot = 4, DashDashDot = 5, Double = -4119, None = -4142, SlashDashDot = 13 } //罫線の太さ public enum XlLineWeight : int { Normal = 2, Medium = -4138, Thick = 4, Thin = 1 } //罫線の描画位置 public enum XlDrawLine : int { Tilt_UpperLeft = 5, Tilt_UpperRight = 6, Edge_Left = 7, Edge_Top = 8, Edge_Bottom = 9, Edge_Right = 10, Inside_Vertical = 11, Inside_Horizon = 12 } }