システムの見積するのに、特定の文字に囲まれた文字列の数を、シート毎、文字列毎に個数を計算する必要がでてきた。
そこで、以下のようなプログラムを作成。
はじめは、Worksheet.UsedRange の各セルを全部調べてましたが、あまりにも遅くて・・・(^^;
そこで、WorkSheet.UsedRangeで取得したRangeのFindとFindNextを使うことで数十倍速く・・・
はじめからこうすればよかったのね。
Sample
------
// 参照の追加で、COMコンポーネント「Micorosoft Excel 11.0 Object Library」の追加が必要
// COMコンポーネントの追加については、最後の記述を参照
using System.Runtime.InteropServices;
using System.Collections;
using System.IO;
using ExcelApp = Microsoft.Office.Interop.Excel;
public void main(){
SortedList
//おまけ
OutputCsvFile(stringListInSheet, ファイル名);
}
public SortedList
{
SortedList
try
{
_excelApp = new ExcelApp.Application();
_excelApp.Visible = false;
_books = _excelApp.Workbooks;
_book = _books.Add(filePath);
_sheets = _book.Sheets;
for (int sheetCounter = 1; sheetCounter <= _sheets.Count; sheetCounter++)
{
try
{
_sheet = (ExcelApp.Worksheet)_sheets.get_Item(sheetCounter);
_range = _sheet.UsedRange;
List
Object missing = System.Reflection.Missing.Value;
ExcelApp.Range findRange = _range.Find(leftSideChar, missing,
ExcelApp.XlFindLookIn.xlValues, ExcelApp.XlLookAt.xlPart,
ExcelApp.XlSearchOrder.xlByRows, ExcelApp.XlSearchDirection.xlNext, true, true, missing);
ExcelApp.Range prevRange;
if (findRange == null)
{
ReleaseAndNullComObj(findRange);
continue;
}
int columnIndex = findRange.Column;
int rowIndex = findRange.Row;
list.AddRange(GetStringBetweenChars((string)findRange.Text, new char[] { leftSideChar[0], rightSideChar[0] }));
prevRange = findRange;
while (findRange != null)
{
// 2度目以降はFindNext
findRange = _range.FindNext(prevRange);
ReleaseAndNullComObj(prevRange);
if (findRange.Column == columnIndex && findRange.Row == rowIndex)
{
break;
}
list.AddRange(GetStringBetweenChars((string)findRange.Text, new char[] { leftSideChar[0], rightSideChar[0] }))
prevRange = findRange;
}
ReleaseAndNullComObj(findRange);
// シート名の出力
stringListInSheet.Add(_sheet.Name, list);
}
finally
{
ReleaseAndNullComObj(_range);
ReleaseAndNullComObj(_sheet);
}
}
}
finally
{
ReleaseAndNullComObj(_sheets);
ReleaseAndNullComObj(_book);
ReleaseAndNullComObj(_books);
_excelApp.Quit();
ReleaseAndNullComObj(_excelApp);
}
return stringListInSheet;
}
private void ReleaseAndNullComObj(object comObj)
{
if (comObj == null)
return;
Marshal.ReleaseComObject(comObj);
comObj = null;
}
private List
{
int leftSideIndex = -1;
List
for (int i = 0; i < source.Length; i++)
{
if (source[i] == sideChars[0])
{
if (leftSideIndex == -1)
leftSideIndex = i;
continue;
}
else if (source[i] == sideChars[1])
{
if (leftSideIndex != -1)
{
result.Add(source.Substring(leftSideIndex + 1, i - 1 - leftSideIndex));
leftSideIndex = -1;
}
}
}
return result;
}
// おまけ
private void OutputCsvFile(SortedList
{
using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.Unicode))
{
writer.WriteLine("シート名\t文字列\t数");
Dictionary
foreach (string key in data.Keys)
{
statisticsData = new Dictionary
foreach (string value in data[key])
{
if (!statisticsData.ContainsKey(value))
statisticsData[value] = 1;
else
statisticsData[value]++;
}
foreach (string value in statisticsData.Keys)
{
writer.WriteLine("{0}\t{1}\t{2}", key, value, statisticsData[value]);
}
}
}
}
COMコンポーネントは、Excelのセットアップでインストール項目として、 [.NET プログラミング サポート]を選んでインストールする必要があります。
http://www.microsoft.com/japan/msdn/office/office2003/OfficePrimaryInteropAssembliesFAQ.aspx
http://msdn.microsoft.com/ja-jp/library/kh3965hw(VS.80).aspx
なお、以下のURLからダウンロードしてインストールすることもできます。
http://www.microsoft.com/downloads/details.aspx?familyid=3c9a983a-ac14-4125-8ba0-d36d67e0f4ad&displaylang=en