using System;
using System.Reflection;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace Nanika
{
///
/// Excel ファイルからテキストやテーブルを取得するためのクラス
/// 作成したオブジェクトは必ず Dispose() により破棄すること
///
public class ExcelText : IDisposable
{
private Excel.Application _application = null;
private Excel.Workbook _book = null;
private Excel.Worksheet _sheet = null;
private Excel.Range _range = null;
private int _numRows = 0;
private int _numColumns = 0;
public int NumRows
{
get { return _numRows; }
}
public int NumColumns
{
get { return _numColumns; }
}
///
/// Excel.Application の開始
///
public ExcelText()
{
_application = new Excel.Application();
}
///
/// Excel.Application の終了
///
~ExcelText()
{
Dispose();
}
///
/// Excel.Application の終了
///
public void Dispose()
{
if (_application != null)
{
CloseBook();
_application.Quit();
_application = null;
}
}
///
/// Excel ブックを閉じる
///
/// 閉じる Excel ブック
private void CloseBook(Excel.Workbook book)
{
if (book != null)
{
_application.DisplayAlerts = false;
book.Close(false, Missing.Value, Missing.Value);
}
}
///
/// Excel ブックを閉じる
///
public void CloseBook()
{
if (_book != null)
{
CloseBook(_book);
_book = null;
}
}
///
/// Excel ブックを開く
///
/// Excel ブックのパス
public void OpenBook(string bookPath)
{
Excel.Workbook excelBook = _application.Workbooks.Open(
bookPath, Missing.Value, true, Missing.Value,
Missing.Value, Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value, Missing.Value,
Missing.Value, Missing.Value, Missing.Value);
CloseBook();
_book = excelBook;
}
///
/// エクセルシートを閉じる
///
public void CloseSheet()
{
if (_sheet != null)
_sheet = null;
}
///
/// Excel シートを開く
///
/// Excel シートの名前
public void OpenSheet(string sheetName)
{
Excel.Worksheet excelSheet =
(Excel.Worksheet)_book.Worksheets[sheetName];
_sheet = excelSheet;
ModifyRange();
}
///
/// Excel シートを開く
///
/// Excel ブックの名前
/// Excel シートの名前
public void OpenSheet(string bookPath, string sheetName)
{
OpenBook(bookPath);
OpenSheet(sheetName);
}
///
/// 開いた Excel シートの有効範囲を取得する
///
private void ModifyRange()
{
_range = _sheet.UsedRange;
_numRows = _range.Rows.Count;
_numColumns = _range.Columns.Count;
}
///
/// 改行を含む特殊なセルからエスケープ文字を取り除く
///
/// 元テキスト
private static string ParseCellText(string cellText)
{
if (cellText.Contains("\n") == false)
return cellText;
string parsedCell =
cellText.Substring(1, cellText.Length - 2);
return parsedCell.Replace("\"\"", "\"");
}
///
/// Excel シートから取得したテキストをテーブルに変換する
///
/// 改行が含まれているセルは正しく変換できない
/// Excel シートから取得したテキスト
/// 列数
/// 行数
/// テーブル
private static string[,] ParseRangeText(
string text, int numColumns, int numRows)
{
string[] cells = text.Split('\t');
string[,] textTable = new string[numRows, numColumns];
for (int index = 1, y = 0; y < numRows; y++, index++)
{
for (int x = 0; x < numColumns; x++, index++)
textTable[y, x] = ParseCellText(cells[index]);
}
return textTable;
}
///
/// Excel シートから指定範囲を取得してテーブルにする
///
/// 行の境界判定を容易にするために複製を使用
/// 指定範囲から取得したテキスト
private string[,] GetRangeTable(Excel.Range range)
{
int numRows = range.Rows.Count;
int numColumns = range.Columns.Count;
// 複製を格納するための Excel シートを用意する
Excel.Workbooks books = _application.Workbooks;
Excel.Workbook newBook = books.Add(string.Empty);
Excel.Worksheet newSheet = (Excel.Worksheet)newBook.ActiveSheet;
Excel.Range newRange = newSheet.get_Range(newSheet.Cells[1, 1],
newSheet.Cells[numRows, numColumns + 2]);
// 空白のセルでテーブルの必要な領域を埋める
newRange.get_Resize(numRows, numColumns);
string[,] emptyTable = new string[numRows, numColumns + 2];
newRange.set_Value(Missing.Value, emptyTable);
// クリップボードを介してテキストを取得する
range.Copy(newSheet.Cells[1, 2]);
newRange.Copy(Missing.Value);
string text = Clipboard.GetText();
CloseBook(newBook);
return ParseRangeText(text, numColumns, numRows);
}
///
/// 開いている Excel シートからテキストを取得する
///
/// Excel シートから取得したテキスト
public string[,] GetTable(
int startColumn, int startRow, int numColumns, int numRows)
{
int endColumn = startColumn + numColumns;
int endRow = startRow + numRows;
if (startColumn < 0 || startRow < 0 ||
endColumn > _numColumns || endRow > _numRows ||
startColumn >= endColumn || startRow >= endRow)
throw new ArgumentOutOfRangeException();
Excel.Range range = _range.get_Range(
_range.Cells[startRow + 1, startColumn + 1],
_range.Cells[endRow, endColumn]);
return GetRangeTable(range);
}
///
/// 開いている Excel シートからテキストを取得する
///
/// Excel シートから取得したテキスト
public string[,] GetTable()
{
return GetRangeTable(_range);
}
///
/// 開いている Excel シートから行テキストを取得する
///
/// Excel シートから取得した行テキスト
public string[,] GetRows(int startRow, int numRows)
{
return GetTable(0, startRow, _numColumns, numRows);
}
///
/// 開いている Excel シートから行テキストを取得する
///
/// Excel シートから取得した行テキスト
public string[] GetRow(int rowId)
{
string[,] table = GetRows(rowId, 1);
string[] row = new string[table.GetLength(1)];
for (int i = 0; i < table.GetLength(1); i++)
row[i] = table[0, i];
return row;
}
///
/// 開いている Excel シートから列テキストを取得する
///
/// Excel シートから取得した列テキスト
public string[,] GetColumns(int startColumn, int numColumns)
{
return GetTable(startColumn, 0, numColumns, _numRows);
}
///
/// 開いている Excel シートから列テキストを取得する
///
/// Excel シートから取得した列テキスト
public string[] GetColumn(int columnId)
{
string[,] table = GetColumns(columnId, 1);
string[] column = new string[table.GetLength(0)];
for (int i = 0; i < table.GetLength(0); i++)
column[i] = table[i, 0];
return column;
}
}
}