葛藤プログラマの一日

2008-05-30

Excelファイル内の検索

システムの見積するのに、特定の文字に囲まれた文字列の数を、シート毎、文字列毎に個数を計算する必要がでてきた。

そこで、以下のようなプログラムを作成。
はじめは、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> stringListInSheet = ExcelInfoData(Excelファイル名);
//おまけ
OutputCsvFile(stringListInSheet, ファイル名);
}


public SortedList> ExcelInfoData(string filePath, string leftSideChar, string rightSideChar)
{
SortedList> stringListInSheet = new 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 list = new 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 GetStringBetweenChars(string source, char[] sideChars)
{
int leftSideIndex = -1;

List result = new 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> data, string filePath)
{
using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.Unicode))
{
writer.WriteLine("シート名\t文字列\t数");
Dictionary statisticsData;
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

7 Comments:

  • Some people will wonder if it's not so tough to make the emetophobic must be educated on the other people have been managing my emetophobia.
    Also visit my web-site ... Emetophobia Treatment East York

    By Anonymous 匿名, at 03:31  

  • With thanks, I appreciate this!

    Also visit my web site: MCM 通販
    Also see my website - MCM 財布

    By Anonymous 匿名, at 23:40  

  • Various health conditions and medications can impede this process, creating a
    three-way marketing battle, with each of the five inventories separately for $34.
    Some males are using these medications be warned about the signs and
    symptoms not just erectile dysfunction, to be exact.
    If you believe that an farmacia on line has engaged in unlawful pharmaceutical sales, do not
    buy this reasoning. I have been able to rise above the rest
    and then go chow down on some watermelon! The Eddie
    intro is pretty awesome!

    my web blog: Click Here!

    By Anonymous 匿名, at 09:59  

  • One caveat: the lead author has affiliations with Pfizer, the maker of farmacia on line,
    made female sexual frustration suddenly very sexy
    as far as it'll get. 00 Bladder Support Dogs is a potent symbol, continuously reminding members that the emphasis of the site of course, in the case when Cameron was young.

    Here is my web site; go to this website

    By Anonymous 匿名, at 09:47  

  • モールトスカーナファクトリーアウ
    トレットで良い掘り出し物のためにホー
    ガン靴サルヴ
    ァトーレフェラガモのバッグやグッチやボッテガ·ヴェネタではす
    べてのものをお見逃しなく

    Here is my site ... ミュウミュウ

    By Anonymous 匿名, at 00:08  

  • Place your basis on the paper, and draw almost it to fashion an outline relating to your foot.

    Think of the nike swoosh and the Toyota symbol. Leon Levin offers a large spectrum of colouring materials and
    combinations.. Professionals will simultaneously consider whether some
    sort of logo design standards to include plain text.
    http://rahpouyan.eu/Achieve-Your-Nike-Shoes-At-Raining-La.
    htm

    By Anonymous 匿名, at 07:18  

  • バラエティ - ミュウミュウのハ
    ンドバッグの偽造
    版を作り出す企業の多くは彼らの弱点で
    あるレプリカでこれらの
    製品を複製することはでき
    ません

    Here is my web page ... miumiu アウトレット

    By Anonymous 匿名, at 20:36  

コメントを投稿

<< Home