【NetOffice】方法 : プログラムを使用してワークシート内のデータを並べ替える

  • 2012.11.11 Sunday
  • 22:04
JUGEMテーマ:コンピュータ



Source and Project

Microsoft.Office.Interop.Excelでできる事は、NetOfficeでも似たようなコードで実現できるのではないか!?という安易な発想でMSDNに書かれているコードを試してみることにします。

今回は

方法 : プログラムを使用してワークシート内のデータを並べ替える
http://msdn.microsoft.com/ja-jp/library/wxks80sb(v=vs.80).aspx

RangeオブジェクトのSortメソッドを利用すれば、ソートが実現できそうです。が!メソッドのオーバーロードがいっぱいあります。引数が多いもので15個もあります。Action/Funcなどの引数の限界に近い数です(Actionが16個、Funcがプラス戻り値で17個でした)。

using System;
using System.Linq;
using NetOffice.ExcelApi;
using NetOffice.ExcelApi.Enums;

namespace Art55.NetOfficeDemo20121111_003
{
    class Program
    {
        static void Main()
        {
            // 方法 : プログラムを使用してワークシート内のデータを並べ替える
            // http://msdn.microsoft.com/ja-jp/library/wxks80sb(v=vs.80).aspx

            var application = new Application { Visible = true };
            Workbook workbook = application.Workbooks.Add();
            var worksheet = workbook.Sheets.OfType<Worksheet>().First();

            var items = new object[,]
                {
                    {3,2,1,1,1},
                    {5,3,1,1,1},
                    {4,1,1,1,1},
                    {1,2,1,1,1},
                    {1,1,1,1,1},
                    {5,2,1,1,1},
                    {5,1,1,1,1},
                    {3,1,1,1,1},
                    {4,2,1,1,1}
                };

            Console.ReadLine();

            var range = worksheet.Range(
                worksheet.Cells[1, 1],
                worksheet.Cells[items.GetLength(0), items.GetLength(1)]);
            range.Value = items;

            // Excelの機能を利用してソートする。
            range.Sort(
                range.Columns[1], XlSortOrder.xlAscending,
                range.Columns[2], Type.Missing, XlSortOrder.xlAscending,
                Type.Missing, XlSortOrder.xlAscending,
                XlYesNoGuess.xlNo, Type.Missing, Type.Missing,
                XlSortOrientation.xlSortColumns,
                XlSortMethod.xlPinYin,
                XlSortDataOption.xlSortNormal,
                XlSortDataOption.xlSortNormal,
                XlSortDataOption.xlSortNormal);

            Console.ReadLine();

            // 配列をソートする。
            range.Value = ((object[,]) range.Value)
                .Convert()
                .OrderByDescending(item => item.ElementAt(0))
                .ThenBy(item => item.ElementAt(1))
                .ToArray()
                .Convert();

            Console.ReadLine();
        }

    }

    public static class ArrayUtils
    {
        public static object[][] Convert(this object[,] items)
        {
            int columnCount = items.GetUpperBound(1) - items.GetLowerBound(1) + 1;
            var result = new object[items.GetUpperBound(0) - items.GetLowerBound(0) + 1][];
            items
                .Cast<object>()
                .Select((value, index) => new { Value = value, RowIndex = index / columnCount })
                .GroupBy(pair => pair.RowIndex)
                .ToList()
                .ForEach(g => result[g.Key] = g.Select(pair => pair.Value).ToArray());
               
            return result;
        }

        public static object[,] Convert(this object[][] items)
        {
            var result = new object[items.Length, items.First().Length];
            items
                .Select((item, index) => new {Value = item, RowIndex = index})
                .ToList()
                .ForEach(pair =>
                    Enumerable
                    .Range(0, result.GetLength(1))
                    .ToList()
                    .ForEach(columnIndex =>
                        result[pair.RowIndex, columnIndex] = items[pair.RowIndex][columnIndex]));
            return result;
        }
    }
}

MSDNに書かれているサンプルコードのネタ元がよく分からなかったので、サンプルのデータはこちらで勝手に用意したものです。
 var items = new object[,]
{
{3,2,1,1,1},
{5,3,1,1,1},
{4,1,1,1,1},
{1,2,1,1,1},
{1,1,1,1,1},
{5,2,1,1,1},
{5,1,1,1,1},
{3,1,1,1,1},
{4,2,1,1,1}
};

■Excelの機能を利用してソートする。
ange.Sort(
range.Columns[1], XlSortOrder.xlAscending,
range.Columns[2], Type.Missing, XlSortOrder.xlAscending,
Type.Missing, XlSortOrder.xlAscending,
XlYesNoGuess.xlNo, Type.Missing, Type.Missing,
XlSortOrientation.xlSortColumns,
XlSortMethod.xlPinYin,
XlSortDataOption.xlSortNormal,
XlSortDataOption.xlSortNormal,
XlSortDataOption.xlSortNormal);

引数の数が多いため、何をしているのか分かりづらいです。実装がどうなっているのか分からないので、正確な言い方ではありませんが、2番目のカラムでソートして、1番目のカラムでさらにソートしているようなイメージです。

実行してみると

ソート前)


ソート後)



Sortメソッドをオーバーロードを羅列してみると

public object Sort();
public object Sort(object key1);
public object Sort(object key1, XlSortOrder order1);
public object Sort(object key1, XlSortOrder order1, object key2);
public object Sort(object key1, XlSortOrder order1, object key2, object type);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase, XlSortOrientation orientation);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase, XlSortOrientation orientation, XlSortMethod sortMethod);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase, XlSortOrientation orientation, XlSortMethod sortMethod, XlSortDataOption dataOption1);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase, XlSortOrientation orientation, XlSortMethod sortMethod, XlSortDataOption dataOption1, XlSortDataOption dataOption2);
public object Sort(object key1, XlSortOrder order1, object key2, object type, XlSortOrder order2, object key3, XlSortOrder order3, XlYesNoGuess header, object orderCustom, object matchCase, XlSortOrientation orientation, XlSortMethod sortMethod, XlSortDataOption dataOption1, XlSortDataOption dataOption2, XlSortDataOption dataOption3);

引数が多すぎて、やる気を失うレベルでした。

■Excelの機能を使わずにソート
Excelの機能を使わずにソートすればいいじゃないかと思いまして書いてみました。

range.Value = ((object[,]) range.Value)
                .Convert()
                .OrderByDescending(item => item.ElementAt(0))
                .ThenBy(item => item.ElementAt(1))
                .ToArray()
                .Convert();

OrderByやThenByを利用すれば簡単だと思っていたのですが、いやはやRange.Valueが返してくる多次元配列の扱いが結構面倒くさいと言うことが分かりました。今回は、二次元の多次元配列から二次元のジャグ配列へ、二次元のジャグ配列から二次元の多次元配列へ変換するメソッドを急造した対応しました。
VBAで書く場合は、Range.Sortを使うのが一般的なのかな・・・わかりません。

Source and Project

--------------------------------------
本投稿は、CodePlexで公開されているNetOfficeを利用しています。
NetOffice - MS Office in .NET
http://netoffice.codeplex.com/

NetOffice関連の記事は下記にまとめています。
【NetOffice】【Excel】NetOfficeのまとめ
http://pro.art55.jp/?eid=1304102
--------------------------------------

コメント
コメントする








    
この記事のトラックバックURL
トラックバック

calendar

S M T W T F S
1234567
891011121314
15161718192021
22232425262728
293031    
<< July 2018 >>

あわせて読みたい

あわせて読みたいブログパーツ

selected entries

categories

archives

recent comment

  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    art55 (05/22)
  • 【キーボード】6年前のRealForceを復活させることはできる!?その3
    分解大好き (05/18)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/04)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    Gen (02/04)
  • 【キーボード】RealForce が壊れて帰ってきた。
    art55 (04/29)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    art55 (02/23)
  • 【.NET Framework 4.5】 IListがIReadOnlyListを継承してない理由。
    かるあ (02/22)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    art55 (01/16)
  • 【C#】Dictionaryの実装・データ構造・アルゴリズムを観察する。
    karuakun (01/16)
  • 【NetOffice】【Excel】死なないExcelプロセスをKillする。
    art55 (12/05)

recent trackback

recommend

recommend

recommend

C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION)
C#プログラマのための.NETアプリケーション最適化技法 (Programmer's SELECTION) (JUGEMレビュー »)
Sasha Goldshtein,Dima Zurbalev,Ido Flatow,サシャ・ゴルドシュタイン,ディマ・ズルバレフ,イド・フラトー

recommend

ろんりと集合
ろんりと集合 (JUGEMレビュー »)
中内 伸光
とてもわかりやすいです。

recommend

recommend

シャノン・ノイマン・ディジタル世界
シャノン・ノイマン・ディジタル世界 (JUGEMレビュー »)
市川 忠男
4章がリレーショナルデータベースな内容になってます。ページ数があまりありませんが、ポイントがものすごく的確にまとまっていて、感動します。

recommend

recommend

東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS
東プレ Realforce91UBK-S 静音キーボード 静電容量無接点方式 変荷重 ブラック NG01BS (JUGEMレビュー »)

テンキーレス、静音のRealForce91UBK-S。スコスコ感がたまらなく気持ちいいです。家と会社で2台持ってます。

recommend

recommend

プログラミング.NET Framework 第4版 (プログラミングシリーズ)
プログラミング.NET Framework 第4版 (プログラミングシリーズ) (JUGEMレビュー »)
Jeffrey Richter
発売予定美 2013年10月10日。.NET Frameworkとお付き合いする人のバイブルですね。

recommend

recommend

キャット・シッターの君に。
キャット・シッターの君に。 (JUGEMレビュー »)
喜多嶋 隆
私のイラストレータデビュー本です。

recommend

Essential .NET ― 共通言語ランタイムの本質
Essential .NET ― 共通言語ランタイムの本質 (JUGEMレビュー »)
ドン・ボックス,クリス・セルズ,Don Box,Chris Sells,吉松 史彰

links

profile

search this site.

others

mobile

qrcode

powered

無料ブログ作成サービス JUGEM