Feeds:
投稿
コメント

Archive for 2012年10月

ColorIndexをEnumにする

未だにWin8にアップグレードできていません

さて、今回はExcelその他のColorIndexを列挙子にしてみます。(作ってからググったらあったけど気にしない)

ColorIndexはColorと違い定義済みの色をそれに対応する整数値から取得、設定することができます
ですがこの整数値はIntegerで入れる形となっていて非常に扱いづらいです(というのもどれがどの色に対応しているかが数字から見えないため)

というわけで数字と対応する列挙子を作成します。列挙子はIntegerで宣言しておけばIntとしても使えるためです

ColorIndexをカラーコードに変換した表についてはググったりすれば簡単に出てくるので楽だと思います。
ちなみに私はhttp://d.hatena.ne.jp/ogohnohito/20110512/p2を参考にさせていただきました
またカラーコードと色名についてはhttp://e-words.jp/p/r-colornames.htmlのほうを参照しました

とりあえず次のような感じ

Public Enum ColorIndexEx
        ''' <summary>
        ''' #000000,ColorIndex = 1に対応する
        ''' </summary>
        Black = 1
        ''' <summary>
        ''' #FFFFFF,ColorIndex = 2に対応する
        ''' </summary>
        White = 2
        ''' <summary>
        ''' #FF0000,ColorIndex = 3に対応する
        ''' </summary>
        Red = 3
        ''' <summary>
        ''' #00FF00,ColorIndex = 4に対応する
        ''' </summary>
        Lime = 4
        ''' <summary>
        ''' #0000FF,ColorIndex = 5,32に対応する
        ''' </summary>
        Blue = 5

End Enum

1から56まであります
少し重複があるのでそこをはじく必要があるので注意

ついでにxlColorIndexについても定義していまうと置き換えられるかと

さて、一つだけ問題があります
17以降がHTMLのカラーコードとしてないという事態です
#9999FFは何色なんでしょうか…

苦肉の策で_9999FF = 17とか宣言してますがなかなかひどい

一応ソースはhttps://bitbucket.org/fantasticswallow/intellioffice/src/ab714c2581f617d3f443c903fca39b3998ab1d64/IntelliOffice/ColorIndexEx.vb?at=defaultに転がっていますので適当に使いたければ(一応Ms-PLにしたいんですけどどうしたらいいんですかね)

とりあえずこの辺で

広告

Read Full Post »

VB.NET 11の新機能を最近知ったなど

さて、Yieldってなんだって話からですがこれはC#には2.0の時くらいからすでにあるyield returnの機能です
Yieldでyield returnが実行されます。yield breakはなさそう

ちょっと少し話が前後しますが最初に戻して進めます

・VB.NET 11での新機能
http://msdn.microsoft.com/en-US/library/we86c8x2.aspxを参照にしながら

書いてあるのは次の通りですね
・Async/Await
・Iterator/Yield
・呼び出し階層
・メソッド情報
・Global Namespaceのサポート

簡単なのはGlobal Namespaceですかね。これは今までルート名前空間に強制的に所属させられていたVB.NETですがGlobalを最初につけることでルート名前空間をつけなくて済みます
つまりSystem.linqに新しくクラス追加しようと思ったときいちいちルート名前空間をSystemにしなくてもGlobal.System.linqにすればいいわけです

メソッド情報は引数に属性をつけることで引数として現在の実行メソッド情報をとれる…?やつなんですかねぇ。これは分かりません

呼び出し階層はスタックトレースみたいのが取れるんじゃないかなぁと

Async/Awaitは非同期待機のやつですね。いくらでも書いてありそうなのでここではスルー

さて、最後にIterator/Yieldですがこれは反復子を指しますIteratorで宣言された関数はReturnの代わりにYieldで返す必要があります

・Iterator/Yield
ちゃんと見ていきます

[accessmodifier] Iterator (Function|Property)の戻り値はIEnumerable(Of T)またはIEnumerator(Of T)となります。(?) 
またYieldは遅延実行することを示します。

Yieldは主にLINQで使われてたりするものです。つまるところ必要になるまでメソッドは実行されずに必要になったら評価されて実行されます。
少しコードを書いて試してみましょう

・yield returnの実行順序
次のようなソースコードを用意します。コンソールアプリケーションです

Private Iterator Function GetIterator(xcol As String) As IEnumerable(Of Char)
    For Each xch In xcol
        Yield xch
        Console.WriteLine("validation value")
    Next
End Function

Sub Main()
    Dim testArgs As IEnumerable(Of Char) = GetIterator("abcdefghijklmnopqr")
    For Each x In testArgs
        Console.WriteLine(x)
    Next
    Console.WriteLine("end test")
End Sub

この実行結果は次の通りです

画像のとおり、yieldでリターンするとYield句まできた時点でメソッドはブロックされ、元の処理に戻されます。
そのためYieldの下のブロックは戻ってきたときにふたたび次のYieldまで実行されます

そのため上の画像のようにFor Each中に値の評価を行います。For Eachしたからといってすべてが一斉に返されないのも特徴といえるかもしれません

・Whereを実装してみる
yield return知りたいならLINQのWhereとか実装するといいといわれたので

自分でVB.NETでWhereを実装すると次のような感じです

Private Iterator Function myWhere(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, Boolean)) As IEnumerable(Of T)
    For Each x As T In source
        If predicate(x) Then Yield x
    Next
End Function

これで次のようなコードを実行してみます

Sub Main()
    Dim testArgs As IEnumerable(Of Integer) = Enumerable.Range(1, 200)
    For Each i In myWhere(testArgs, Function(x) x Mod 5 = 0)
        Console.WriteLine(i)
    Next
    Console.WriteLine("end test")
End Sub

実行結果は…まあ普通のWhereの結果です

Selectは次のような感じでいいのかな?(テストできてない)

Private Iterator Function mySelect(Of T, TValue)(source As IEnumerable(Of T), predicate As Func(Of T, TValue)) As IEnumerable(Of TValue)
    For Each x As T In source
        Yield predicate(x)
    Next
End Function

・どこで使うの
まあ基本はLINQみたいにコレクション操作になるとは思いますがYieldでやる必要がありなおかつLINQでサポートされてないメソッドというのがそんなにたくさん出てくるのか微妙な気は
そもそも.NET Framework 4.5なのでLINQでサポートしてる内容をわざわざYieldで使う必要ってないんですよね

LINQの理解のために使うとかLINQわからないからYield… くらい…?
それよりはやっぱりLINQとかでサポートしてないやつになるかなぁ…


結局使用方法が見いだせず…
というか前半の文面なんも考えてなかったせいでわかりづらいですね

とりあえずこの辺で

Read Full Post »

作ろうと思ってたライブラリの内容がもろ入ってて笑うどころではないなど

というわけでVSTO Power Toolsのお話です。4年は前のツールですね
これのインストールのためだけにVisual Studio 2008入れることになるとは…

Microsoft Visual Studio Tools for the Office System Power Tools v1.0.0.0はVSTO向けの便利なアプリケーションや拡張アセンブリを提供してくれるものです
OpenXMLのビューアやビルトインされたリボンのコントロールIDを選択したり?するアプリケーションなどを含んでいます。アプリケーションの方は興味があったら調べるといいかもしれません

今回話題にするのはOffice Interop API Extensionsという拡張アセンブリの方です。これの説明には”A set of C# classes for handling parameterized properties and optional/named parameters, as well as for LINQ-enabling Office collection objects.” とあります。つまりOptionalなプロパティのObjectにされてた部分をしっかり型の関連付けを行い、LINQを使えるようにもしたよって感じです

まず一つ目になんで型の関連付けがすごくいいかというお話ですがVSTOではこんな感じのメソッドが多めに用意されています

Microsoft.Office.Interop.Excel.PivotTable PivotTableWizard(
    [object SourceType = System.Type.Missing], 
    [object SourceData = System.Type.Missing], 
    [object TableDestination = System.Type.Missing], 
    [object TableName = System.Type.Missing], 
    [object RowGrand = System.Type.Missing], 
    [object ColumnGrand = System.Type.Missing], 
    [object SaveData = System.Type.Missing], 
    [object HasAutoFormat = System.Type.Missing], 
    [object AutoPage = System.Type.Missing], 
    [object Reserved = System.Type.Missing], 
    [object BackgroundQuery = System.Type.Missing], 
    [object OptimizeCache = System.Type.Missing], 
    [object PageFieldOrder = System.Type.Missing], 
    [object PageFieldWrapCount = System.Type.Missing], 
    [object ReadData = System.Type.Missing], 
    [object Connection = System.Type.Missing])

こんなメソッドどうでしょうか

何がすごいってまずVSTOなのにインテリセンスが使えないところにあります。それなりにはでますけど…
というか何入れていいのかこれだけじゃさっぱりわかりません。下手なの入れると動かないですし

これを拡張メソッドで簡単に書き換えるとこんな感じになります(VBですが)

'' <summary>
        ''' Worksheet.PivotTableWizardを実行します
        ''' </summary>
        ''' <param name="target"></param>
        ''' <param name="SourceType">レポートの集計元データの内容を示す定数。この引数を指定する場合は引数SourceDataも指定。
        ''' SourceTypeとSourceDataを省略した場合、集計元データの種類はxlDatabaseとされ、集計元データは名前付きセル範囲Databaseから取得されます。
        ''' 名前付きセル範囲Databaseが存在しないときに、現在の選択範囲がデータを含む10以上のセルの場合は、その選択範囲が使われます。そうでない場合はエラーが発生します。</param>
        ''' <param name="SourceData">レポートの作成に使うデータ。Rangeオブジェクト、セル範囲の配列、他のレポートの名前を表す文字列定数のいずれかを指定可能。外部データベースの場合、引数SourceDataは、各要素が255文字の長さまでのSQLのクエリ文字配列を格納。
        ''' 引数Connectionを使って、ODBC接続文字列を指定。以前のExcelのバージョンとの互換性について、SourceDataでは2つの要素配列を指定できます。
        ''' 1番目の要素はデータのODBCソースを指定した接続文字列です。2番目の要素はデータの取得に使用するSQLのクエリ文字列です。引数SourceDataを指定した場合、引数SourceTypeも指定する必要があります。
        ''' 引数SourceDataの範囲内にアクティブセルがある場合は、引数TableDestinationも指定する必要があります。</param>
        ''' <param name="TableDestination">レポートの配置場所を表すRangeオブジェクト</param>
        ''' <param name="TableName">新しいレポートの名前</param>
        ''' <param name="RowGrand">レポートに行の総計を表示するかどうか</param>
        ''' <param name="ColumnGrand">レポートに列の総計を表示するかどうか</param>
        ''' <param name="SaveData">レポートと共にデータを保存するかどうか。Falseの場合はレポートの定義のみ</param>
        ''' <param name="HasAutoFormat">レポートの更新時やフィールドが移動されたときに、オートフォーマットを実行するかどうか</param>
        ''' <param name="AutoPage">SourceTypeにxlConsolidationを指定した場合にのみ有効。統合元範囲のページ フィールドを自動的に作成するかどうか。
        ''' False に指定した場合は、ページ フィールドは自分で作成する必要があります。ページ フィールドは複数作成することができます。</param>
        ''' <param name="BackgroundQuery">レポートのクエリをバックグラウンド(非同期)で実行するかどうか</param>
        ''' <param name="OptimizeCache">ピボットテーブルのキャッシュの構成時に最適化を行うかどうか</param>
        ''' <param name="PageFieldOrder">ピボットテーブルレポートのレイアウトに追加するページフィールドの順序</param>
        ''' <param name="PageFieldWrapCount">ピボットテーブルの各列または各行のページ フィールドの数を指定</param>
        ''' <param name="ReadData">外部のデータベースのすべてのレコードを含む、非常に大きなピボットテーブルキャッシュを作成するかどうか。Falseの場合、実際のデータを読み込む前に、いくつかのフィールドをサーバーを基にしたページフィールドに設定できます。</param>
        ''' <param name="Connection">ODBCデータ ソースと接続できるようにするODBC設定のいずれかを含む文字列。接続文字列は"ODBC;[接続文字列]"形式です。
        ''' この引数は、PivotCache オブジェクトの Connection プロパティの設定よりも優先されます。</param>
        ''' <returns></returns>
        ''' <remarks>Reservedは使用不可につき常にnullがわたります</remarks>
        <Extension()>
        Public Function PivotTableWizard(target As Worksheet,
                 Optional SourceType As XlPivotTableSourceType = Nothing,
                 Optional SourceData As Object = Nothing,
                 Optional TableDestination As Range = Nothing,
                 Optional TableName As String = Nothing,
                 Optional RowGrand As Boolean = Nothing,
                 Optional ColumnGrand As Boolean = Nothing,
                 Optional SaveData As Boolean = Nothing,
                 Optional HasAutoFormat As Boolean = Nothing,
                 Optional AutoPage As Boolean = Nothing,
                 Optional BackgroundQuery As Boolean = False,
                 Optional OptimizeCache As Boolean = False,
                 Optional PageFieldOrder As XlOrder = XlOrder.xlDownThenOver,
                 Optional PageFieldWrapCount As Integer = 0,
                 Optional ReadData As Boolean = Nothing,
                 Optional Connection As String = Nothing) As Microsoft.Office.Interop.Excel.PivotTable

これでもまだ残念な気はしますけどマシではありますね(実際使うかといわれると微妙ですが)(そもそも引数が多い)

こういうのを全部~~Argsという形でまとめてあるのが拡張アセンブリの方です。これによって基本的に引数1つだけできれいに実行できるようになりました。 やってることはMissingへの変換があるせいで微妙に汚いですけど…

次にLINQのサポートのほうなんですけどこれはいくつかのメソッドにIEnumerableを返すItemsという関数が定義されています。中身はオブジェクト本体をyield returnしています。(ILゲフンゲフン)
yield returnなんてVBにないから気づかなかったのか…!(違う) とか思いながらこれを実装すれば何かに使えるかも知れませんね
(まあCOMObjectの壁を越えれるのかは知りませんが…)(どっちかっていうとCastに近い感じが)

さてそんな感じでこんなアセンブリもあるよって話ですが実はこのツール、VS2008までしか対応していません。Officeも12までです。便利なのに今は使うことができないという悲しい現実

VS2008を今でも使ってる方はぜひどうぞ! って感じですがいまさらVS2010も2012でもないのを使うのはちょっと

自分でとりあえず作ってみるかなー的な感じのことは思ってたりですけどね

あとこれ調べてて感じた結論は
「VSTOはC#も使えるんじゃなくてC#のためのOffice開発」
って感じですね。VB.NETなんてなかったんや…

とりあえずこの辺で

Read Full Post »