2009年5月25日月曜日

Avira AntiVir をインストールしたが起動せず

友人の ウィルス対策用のソフト Avast が、なぜか毎回エラーメッセージを表示するようになった。色々調べたけれど理由がわからず。 (+_+) これを機会に Avira AntiVir + Comodo Firewall の組み合わせに変更することにした。

しかし、ここでもまたトラブル。以前から調子の良くない PC だったためか、Avira AntiVir をインストールしてもエラーで起動せず。タスクトレイのアイコンを見ても、傘が閉じたまま。

何度インストールとアンインストールを繰り返しても起動することはなかった。そして、最悪なことに、Avast もインストールできなくなってしまった。これは、途中 PC の調子が悪かったので、レジストリを綺麗にしてくれるソフトを使ってしまったことが原因だったようだ。ついでにユーザのプロファイルも壊れてしまい、新規にユーザを作成することを余儀なくされた。 (@_@;)

もうどうにもならんと匙を投げかけたけれど、PC を起動するときに F8 キーを押して Windows をセーフモードで起動。ダメ元で再度インストールを試みたら問題なくインストールが完了した。 ^^

2009年5月24日日曜日

Haskell で文字列の分割 (2)

Google スプレッドシートで文字列の分割」で、他の言語における同様の処理を見直していたとき、 Haskell における文字列の分割が、正規表現を利用した方法以外にもっとお手軽にできないかと思い探してみると、Data.List.Split があるのに気がついた。

 

インストール

標準ではインストールされていないので、 utf8-string を使えるようにしたときのようにインストール。(cf. 4. Building and installing a package) HackageDB: split-0.1.1 の Download より split-0.1.1.tar.gz をダウンロードして解凍。解凍したフォルダ内において、

runhaskell Setup.hs configure 
runhaskell Setup.hs build
runhaskell Setup.hs install

でインストール。

 

Data.List.Split

The Data.List.Split module contains a wide range of strategies for splitting lists with respect to some sort of delimiter, mostly implemented through a unified combinator interface.

(Data.List.Split より)

試してみる。

import Data.List.Split
main = print $  splitOn "," "hoge,piyo,fuga"

 

日本語でも。ただし、ソースコードのエンコーディングは UTF-8 で、結果をファイルで開くときも UTF8 であることを忘れずに。

import Data.List.Split
import System.IO.UTF8 as U
main = mapM_ U.putStrLn $ splitOn "," "ほげ,ぴよ,ふが"

 

その他

ちなみに、自前で実装する場合は、break 関数を使う

2009年5月23日土曜日

Firefox の Personas で外観をカスタマイズ

数々のアドオンを試してはいても、テーマはデフォルトのままでカスタマイズしたことがない。デザインにこだわりがないわけではないけれど、好きなテーマ見つけてインストールして再起動する手間に対して変化が見合わないからだ。

と、そんな風に考えていたけれど「Firefox、「Personas for Firefox 1.1」リリース:CodeZine」 に

Mozilla Labsでは17日、カラフルなスキンを着せ替えるアドオン「Personas for Firefox 1.1」をリリースした。7,000人以上のデザイナーによる1万を越えるスキンが提供されている。

折角なので Personas for Firefox を試したら、お手軽でよかった。 ^^

 

090522-006設定の素早さ

インストールするとステータスバーに Personas のアイコンが表示されるので、クリック > 直接表示... を選択。

Personas for Firefox | Gallery が表示されたら、各画像の上にカーソルを移動させるだけで一時的にそのペルソナになり、カスタマイズしたときのイメージがしやすい。 ^^

見かけのカスタマイズなんか全く興味がなかったが、これなら変えてみようという気になる。お手軽さというのは、人の行動様式までも変化させるのだとつくづく実感。(@_@)

で、とりあえず Kiwitiki にした。

2009年5月22日金曜日

Google スプレッドシートで文字列の分割 – Split 関数

1. 文字列を分割する関数の名前は split

文字列を分割するメソッドは、たいてい `split’ と名付けられている。

 

2. Google スプレッドシートの split 関数

Google スプレッドシートにも、同じ名前の関数がある。

例えば、セル A1 にコンマ区切りの文字列が入力されている。これをコンマ(,) で分割したい場合 B1 に、

=split(A1,",")
090521-004

B1:F5 に分割された結果が表示される。

 

3. 複数の値を返す数式 - マルチセル配列数式

上記の結果が表示されている、セル B1 の内容を見ると、以下のように表示される。

=CONTINUE(B1, 1, 2)

によると、この意味は、

  1. セル B1 から出力されていて、
  2. その結果の 1 行目 2 列目のエントリーである

ことを示している。

split 関数と同じように、式の結果が複数の値を返すに、ImportHtml 関数 があった。こういった種類の関数のことを、「マルチセル配列数式」という。

マルチセル配列数式では,数式が複数の値を返します。

(関数 : 配列数式 - Google ドキュメント ヘルプ より、太字は引用者による)

2009年5月19日火曜日

「ご利用のブログはスパムと認識されています」(@_@;)

突然 Gmail に Blogger さんより、

ユーザー各位
   ブログ http://jutememo.blogspot.com/ はスパム ブログの可能性があります。… にあるフォームに記入して、ブログの確認をリクエストしてください。
   確認を受けなければ、ブログは 20 日以内に削除され、この間は読者に対して警告ページを表示します …

パタッ(o_ _)o~†

このメールを見たユーザをはめるためのイタズラかと思って、念のため Blogger のダッシュボードを見てみると、

090518-003

パタッ(o_ _)o~†

早速ロック解除の確認をリクエスト。

「ご利用のブログはスパムと認識されています

Blogger のスパム対策ロボットにより、このブログにスパム ブログの疑いがあることが検出されました (スパム ブログとは)。しかしながら、自動システムを使用しておらず、このメッセージをご覧になられている場合は、スパム ブログではないと考えられます。 スパム検出システムは自動化されているため、誤って検出された場合はお詫び申し上げます。

スパム ブログではないことが確認されるまで、読者に対して警告ページが表示されます。確認を希望される場合は、下記のフォームにご記入ください。ブログを確認し、2 営業日以内にロックを解除いたします。

ご連絡いただけない場合は、数週間以内に Blog*Spot からあなたのブログを削除いたします。

Blogger のスパム ブログ対策の詳細については こちらをご覧ください。」

スパム対策ロボットの勘違いだったか… (@_@;) それにしても返答がない場合、容赦なく削除とは恐しや。もし、これに気がつかず長期間放置してたらメモが全部パーかぁ。。

長らくブログをバックアップをしてなかったけれど、やはり定期的にバックアップすることにした。

Excel でリンクを含んだセルから HTML の A 要素を作成

Excel の A 列に特定のサイトへのリンク付きのテキストがある。ここから HTML の

<li><a>サイト名</a></li>

というような文字列を作成したい。

 

方法

単純にハイパーリンクを記入したセルを別のセルから参照すればいいのかと思いきや、参照するとリンクがなくなりテキストだけになってしまう。

090519-001.png

リンクを抽出したい場合、どうすればいいのだろう?

090519-002エクセルのハイパーリンクについて教えて下さい –OKWave を見ると、Range オブジェクトから Hyperlinks コレクションを取得する方法が書かれていた。特定の範囲からリンクのアドレスを抽出するということのようだ。(via  エクセルのハイパーリンクのURLを抽出するため、... - 人力検索はてな)

 

標準モジュールに以下の関数を定義。

Function createHtmlLink(objRange As range) As String
    createHtmlLink = objRange.Hyperlinks(1).Address
End Function

B1 セルに以下を記述して、下方向へフィル。

="<li><a href="""&createHtmlLink(A1)&""">"& A1 & "</a></li>"

結果

  • すぐに忘れる脳みそのためのメモ
  • Home ‎(すぐに忘れる脳みそのための Wiki)‎
  •  

    参考サイト

    COMODO Firewall を日本語表示に変更

    Avast から Avira AntiVir + Comodo Firewall へ」の続き。

    窓の杜 - 【NEWS】フリーの統合セキュリティソフト「COMODO Internet Security」が日本語化 によると、

    …「COMODO Internet Security」v3.9.95478.509を公開した。本バージョンでは、有志らによるメニューなどの翻訳が行われ、新たに日本語をはじめとする19カ国語に対応した。

    早速、日本語表示するために COMODO Firewall を起動。

    ウィンドウ上部のメニューより > MISCELLANEOUS > Settings > Language の Select Language において「日本語 – By Community」を選択した。

    090519-005

    あ~、やっぱ日本語の方が馴染める~ ^^

    090519-006

    2009年5月18日月曜日

    Haskell のモジュールの階層化と、型クラス - パラメータ多相とアドホック多相

    0. 目次

    • 1. 同じ名前のフィールドラベルを持つ型を定義したい
    • 2. モジュールを分割し、階層化する
    • 3. 型の意味
    • 4. 型クラスの役割
    • 5. パラメータ多相と、アドホック多相
    • 6. 多相性とオブジェクト指向
    • 7. 演算子の意味
    • 8. 継承とジェネリクス
    • 9. Ad hoc の意味
    • 10. 型クラスの定義と、インスタンス化
    • 11. 余談: モジュールに分けない場合

     

    1. 同じ名前のフィールドラベルを持つ型を定義したい

    2 つの型が、類似している場合、フィールド名に同じ名前を使いたい。

    例えば、「名前」と「年齢」を持つ、「犬」型を定義する。

    このとき、フィールドラベルを使うなら、

    data Dog = Dog {name :: String, age :: Int} deriving Show

    「犬」型と同様のフィールドを持つ、「猫」型も定義。

    data Cat = Cat {name :: String, age :: Int} deriving Show

    しかし、同一モジュール (ここでは Main モジュール) で、同じフィールド名を持つ型を定義すると、エラーが発生する。 (+_+)

    Multiple declarations of `Main.name'
    ...
    Multiple declarations of `Main.age'
    ...

    理由は、3.15 フィールドラベルをもつデータ型3.15.1 フィールドの選択 によると、、

    フィールド名は選択子関数として使用する。変数として使用するときは、 フィールド名はオブジェクトからそのフィールドを取り出す関数として働く。 選択子はトップレベルの束縛なので局所変数によって覆い隠される。しかし、 同じ名前の他のトップレベルの束縛とは衝突することは出来ない。…

    (太字は引用者による)

    フィールド名は、単なる名前ではなく、フィールドの値を返す関数。名前空間は、トップレベルに所属するので、代数的データ型の中に書いているように見えても、バッティングに注意が必要ということ。

    つまり、以下のように、フィールドラベルは「関数」となるので、同じ名前の関数を二つ作れない。

    *Main> name $ Dog "pochi" 3
    "pochi"

     

    2. モジュールを分割し、階層化する

    では、同じフィールド名を持つ、異なる型を定義したい場合、どうすればいいのだろう?

    2.2.1. Modules vs. filenames によると、

    How does GHC find the filename which contains module M? Answer: it looks for the file M.hs, or M.lhs.

    GHC の場合、各々の型を別モジュールに定義し、別ファイルに含めるということ。

    つまり、先ほどの例の場合、「犬」と「猫」型に対応したモジュールを作成し、それぞれのファイルに記述すれば良い。

    説明に従い、最初に、「犬」型を ファイル Dog.hs に定義。

    module Dog where
        data Dog = Dog {name :: String, age :: Int} deriving Show

    ところで、GHC ではモジュールを階層化できる。

    The Glorious Glasgow Haskell Compilation System User's Guide, Version 6.10.25.6.1. Haskell source files によると、

    Usually, the file should be named after the module name, replacing dots in the module name by directory separators. For example, on a Unix system, the module A.B.C should be placed in the file A/B/C.hs, relative to some base directory.

    モジュールのベースとなるディレクトリを想定し、そこからの相対位置で、モジュール名が決まる。モジュール名は、モジュールを配置したディレクトリの階層に対応させ、`.’ により階層化していることを示すということ。

    例えば、先ほどの「猫」型をやめ、「三毛猫」型を Cat 階層に作りたい。この場合、

    1. Cat ディレクトリを作成し、
    2. 下記のモジュールを Mike.hs に記述し、Cat ディレクトリに配置。
    3. その際、モジュール名は、モジュールを配置したディレクトリに対応させるために Cat.Mike とする。
    module Cat.Mike where
        data Mike = Mike {name :: String, age :: Int}

    全体では、以下のようにファイルを配置する。

    Dog.hs
    Cat
    -- Mike.hs

    ただし、メインモジュールにおいて、フィールドラベルを用いて「名前」を表示したい場合、関数名 (フィールドラベル) をモジュール名で修飾しなくてはならない。

    import Dog
    import Cat.Mike
    main = do print $ Dog.name $ Dog "pochi" 3
              print $ Cat.Mike.name $ Mike "tama" 2

    できることなら、関数を適用するとき、モジュール名で修飾せず、シンプルに name と書きたい。

    そのためには、「型クラス」を使い、関数のオーバーロードを行う必要がある。

     

    3. 型の意味

    その前に、「型」について整理しておく。

    データベース実践講義」の「2.3 型とは」(p34) によると、

    型とはいったい何か。基本的には、値の名前付き有限集合である。…

    すべての型が、その型の値もしくは変数に作用する演算子の連想集合を持つ …

    Data type - Wikipedia, the free encyclopedia には、

    In a broad sense, a data type defines a set of values and the allowable operations on those values.

    つまり、「型」とは

    1. 値の集合と、
    2. その値に対する、操作が定義されたもの。

    上記より、オブジェクト指向における「クラス」を連想した。なぜなら、

    1. 「値」に相当するインスタンスと、
    2. 「操作」に相当するメソッドを持つため。

    Data type - Wikipedia には、型 (データ型) と呼ばれるものには、いくつか種類があることが示されている。

    上記データ型の違いの一例を挙げると、オブジェクト型では、内部状態を持つのに対して、Haskell のような代数的データ型では、値の集合を定義するのみで、操作を定義する場合、別に関数定義する。

     

    4. 型クラスの役割

    では、「型クラス」とは何か?

    Type class - Wikipedia によると、

    Type classes first appeared in the Haskell programming language, and were originally conceived as a way of implementing overloaded arithmetic and equality operators in a principled fashion.

     A Gentle Introduction to Haskell: Classes には、

    There is one final feature of Haskell's type system that sets it apart from other programming languages. The kind of polymorphism that we have talked about so far is commonly called parametric polymorphism. There is another kind called ad hoc polymorphism, better known as overloading.

    Here are some examples of ad hoc polymorphism:

    • The literals 1, 2, etc. are often used to represent both fixed and arbitrary precision integers.
    • Numeric operators such as + are often defined to work on many different kinds of numbers.
    • The equality operator (== in Haskell) usually works on numbers and many other (but not all) types.

    (太字は引用者による)

    型クラスは、Haskell の特徴の一つで、Haskell で初めて導入された。多相性には、パラメータ多相と、アドホック多相があり、後者はオーバーロードと呼ばれる。

    型クラス(Type class - Wikipedia) の説明に戻る。

    a type class is a type system construct that supports ad-hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types. Such a constraint typically involves a type class T and a type variable a, and means that a can only be instantiated to a type whose members support the overloaded operations associated with T.

    090513-002.png上記について、「Haskell の代数的データ型と型クラス、instance 宣言の関係」で使い方を確認した。しかし、そのとき、代数的データ型と、型クラスの関係が理解しにくく、知識として定着しなかった。

    オブジェクト指向におけるオーバーロード、オーバーライドには馴染みがある。しかし、パラメータ多相、アドホック多相、それに加えて、型クラスがどう絡んでいるのかイメージがしずらい。(+_+)

    「アドホック多相は、関数を適用する対象を制約するための手段。 Haskell では、それを型クラスによって実現している。」

    と頭に叩き込もうとした。しかし、直観的に理解できず、しっくり来なかった。 (@_@;)

    090514-006.pngしかし、次のように考えたら、スッキリした。

    1. 型は値をグループ化する。
    2. 型クラスは、型をグループ化する。
    3. その結果、型クラスの制約が付いた関数は、その型クラスのグループに属していない型には適用できない。
    4. インスタンス化とは当該の型クラスに所属する宣言。

     

    5. パラメータ多相と、アドホック多相

    Type polymorphism - Wikipedia によると、Christopher Strachey が、二つの異なる多相について述べていたとのこと。

    それによると、「アドホック多相」とは、

    If the range of actual types that can be used is finite and the combinations must be specified individually prior to use …

    それに対して、「パラメータ多相」とは、

    If all code is written without mention of any specific type and thus can be used transparently with any number of new types …

    つまり、アドホック多相は、関数を適用する型を制限するのに対して、パラメータ多相は、具体的な型について言及しないことにより、新しい型に対応できるようにするということ。

     

    6. 多相性とオブジェクト指向

    パラメータ多相と、アドホック多相は、オブジェクト指向において、どのように対応しているのだろうか?

    Polymorphism (computer science) - Wikipedia によると、

    In object-oriented programming, subtype polymorphism or inclusion polymorphism is a concept in type theory wherein a name may denote instances of many different classes as long as they are related by some common super class.[1] Inclusion polymorphism is generally supported through subtyping, i.e., objects of different types are entirely substitutable for objects of another type (their base type(s)) and thus can be handled via a common interface. Alternatively, inclusion polymorphism may be achieved through type coercion, also known as type casting.

    オブジェクト指向においては、サブタイプ多相と呼ばれる。オブジェクトが、共通のインターフェイスを実装している場合、他のオブジェクトに置き換えることができるというもの。

    また、Operator overloading - Wikipedia によると、

    (less commonly known as operator ad-hoc polymorphism) …

    operators like +, =, or == have different implementations depending on the types of their arguments.

    演算子オーバーロードは、アドホック多相に相当するとのこと。

    オーバーロードと言えば、以下のようにいくつか種類がある。

  • Function overloading, a software engineering process whereby multiple functions of different types are defined with the same name
  • Operator overloading, a software engineering process whereby operators such as + or - are treated as polymorphic functions having different behaviours depending on the types of arguments used
  • Method overloading a type of polymorphism where different functions with the same name are invoked based on the data types of the parameters passed

    (Overload - Wikipedia, the free encyclopedia より)

  •  

    7. 演算子の意味

    ところで、「演算子」というと、Java しか知らなかったとき、メソッドとの違いを明確にイメージしていた。

    `+’ のように、「メソッド名にできない記号が演算子」と言う意識。

    この Java の仕様は、以下で述べられている。

    Sun deliberately chooses not include operator overloading in the Java language.

    (Operator overloading - Wikipedia, the free encyclopedia より)

    Ruby は Java と違い、再定義可能な演算子 がある。

    |  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
    +  -  *  /    %   **   ~   +@  -@  []  []=  `

    Haskell は、 Haskell 98 字句構造 で述べられている。

    Python は、__XXXXX__() という形の 特殊メソッド を、クラスが実装することによって、同様のことが可能。

    そういえば、Haskell に触れるようになってから、関数と演算子の差異をあまり感じなくなった。なぜなら、関数の中置記法があるため。

    演算子 – Wikipedia とは、

    コンピュータプログラミングにおいては、主に記号を用いて演算を指示するものが演算子と呼ばれる。概ね数式などの記述を模倣しているが、一部の演算子に通常と異なる記号が用いられたり、副作用を持っていることがあるなど、数学の演算子とは異なる点もある。

    関数 f(x) の "f( )" も単項演算子であり、符牒となる文字列 "f" を関数子などと呼ぶ場合もある。関数子としては任意の文字列を使用することができ、代表的なものとして三角関数 "sin", "cos", "tan" などが挙げられる

    つまり、演算子も関数も、使える記号と記法が違うだけで、本質的な違いはない。

    考えてみれば、メソッドオーバーロードは、同一クラス内で、異なる引数に対する処理に、同じ名前を付けること。メソッドの引数を、関数プログラミングで言う適用する対象と見れば、メソッドオーバーロードは、メソッドが所属するクラスは同じでも、適用する対象が異なるという点で、演算子オーバーロードと似ている。

    「メソッドのシグニチャは、なぜ返り値を含まないんだ?」

    と、以前から疑問に思っていた。しかし、1 + 2 と 3 + 4 の結果、型が異なるような実装ができたらおかしいか。

     

    8. 継承とジェネリクス

    話を戻して、オブジェクト指向におけるアドホック多相とは、オーバーロードに相当する。

    先に挙げた Christopher Strachey  の言うところの

    「メソッドの引数の型がある範囲に限られている」

    ということによる。

    型が「限られている」という点から見ると、

    Ad-hoc polymorphism is generally supported through object inheritance, …

    (Type polymorphism - Wikipedia より)

    オブジェクト指向の継承も、アドホック多相に相当する。

    逆に、「限定されていない」と言うのは、090518-002.png

    In the object-oriented programming community, programming using parametric polymorphism is often called generic programming.

    ジェネリクスのこと。

     

    9. Ad hoc の意味

    ところで、「アドホック」というと

    アドホックな仮説 - Wikipedia

    という使われ方を連想する。言葉自体に、良いイメージがない。

    そもそもの意味は Yahoo!辞書 - ad hoc によると、

    ((限定))そのためだけに[の], 特別に[な]

    Ad hoc - Wikipedia には、

    Ad hoc is a Latin phrase which means "for this [purpose]". It generally signifies a solution designed for a specific problem or task, non-generalizable, and which cannot be adapted to other purposes.

     

    10. 型クラスの定義と、インスタンス化

    さて、最初の「犬・猫」型のコードに戻る。型クラスを使い、異なる型に、同じ関数名を適用できるようにしたい。

    そのためには、型をグループ化する、型クラスを定義する。

    Name.hs

    module Name where
        class Name a where
                getName :: a -> String

    次に Dog.hs

    module Dog where
        import Name
        data Dog = Dog {name :: String, age :: Int} deriving Show
        instance Name Dog where
               getName (Dog name age) = name

    同じようにして Cat/Mike.hs

    module Cat.Mike where
        import Name
        data Mike = Mike {name :: String, age :: Int}
        instance Name Mike where
                    getName (Mike name age) = name

    ついでに、メインモジュールにおいて、getName 関数を利用して

    「こんにちは!○○.」

    と出力する hello 関数も定義する。

    import Dog
    import Person
    import Name
    import Cat.Mike
    
    hello :: Name a => a -> String
    hello x = "Hello! " ++ getName x ++ "."
    
    main = do print $ getName (Mike "mike" 100)
              putStrLn $ hello (Mike "mike" 30)

     

    11. 余談: モジュールに分けない場合

    もし、モジュールに分けずにシンプルに書くとしたら、

    1. 犬と猫に共通の Pet 型を作り、
    2. そこで名前と年齢を持たせる。

    ついでに、犬と猫を同じ型にして、定義してみた。

    data Pet = Pet { name :: String, age :: Int }
    data MyPet = Dog Pet | Cat Pet
    
    getName :: MyPet -> String
    getName (Dog p) = name p
    getName (Cat p) = name p
    
    main = do print $ getName $ Dog (Pet "Pochi" 10)
              print $ getName $ Cat (Pet "Tama" 3)

     

    関連記事

    関連サイト

    2009年5月14日木曜日

    VBA のバリアント型

    配列の走査

    VBA で文字列の配列の初期化」のついでに配列の走査。変数 strAry が文字列の配列だとすると、

        Dim idx As Integer
        For idx = LBound(strAry) To UBound(strAry)
            Debug.Print strAry(idx)
        Next

    LBound, UBound 関数が記憶の彼方にあって全く思い出せなかった。 (o_ _)o~†

     

    For Each … Next

    For Each を使う場合は、

        For Each elem In strAry
            Debug.Print elem
        Next

    もし、上記に先立ち、

        Dim elem As String

    と宣言すると、

    090513-005

    For Each の場合、要素を指す変数はバリアント型でないといけなかったかぁ。。 (@_@;)

    ヘルプ > Microsoft Visual Basic Documentation > Visual Basic プログラミングのヒント の「For Each...Next ステートメントの使い方」によると、

    For Each...Next ステートメントは、コレクションの各オブジェクトまたは配列の各要素に対して、一連のステートメント ブロックを繰り返し実行します。

    また、「For Each...Next ステートメント」 には、要素が代入される変数について、

    コレクションや配列の各要素を繰り返す変数を指定します。コレクションの場合、引数 element にはバリアント型 (Variant) 変数、総称オブジェクト型変数、または任意の固有オブジェクト型のオブジェクトの変数を指定できます。また、配列の場合は、引数 element にはバリアント型のみ指定できます。

     

    クラスモジュール

    For Each … Next と言えば、オブジェクトのコレクションを走査するときによく使った。例えば、プロパティに「名前」を持つ Person クラスを定義し、

    Dim mstrName As String
    
    Public Property Let Name(strName As String)
        mstrName = strName
    End Property
    
    Public Property Get Name() As String
        Name = mstrName
    End Property

    このクラスのオブジェクトをコレクションに追加し、For Each … Next で走査するには、

        Dim col As New Collection
        
        Dim p1 As New person
        p1.Name = "Tarou"
        Dim p2 As New person
        p2.Name = "Jirou"
        
        col.Add p1
        col.Add p2
        
        Dim person As person
        For Each person In col
            Debug.Print person.Name
        Next

     

    バリアント型

    ところで、バリアント型はあまり使ってなかったので、For Each で使えることを知らなかった。上記でも For Each で使っている要素を代入する変数 person の型宣言をせずにバリアント型としても使用できる。

    ヘルプの「バリアント型 (Variant)」を見ると、

    バリアント型は特殊なデータ型で、固定長の文字列型 (String) データとユーザー定義型を除く、あらゆる種類のデータを格納することができます。

    (太字は引用者による)

    バリアント型というと、文脈に応じて適用する演算子の意味が変化し、メモリを結構使うということしか頭に残っていない。 ^^;

    バリアント型には、特殊な値 Empty 値Null 値、およびエラー値や Nothing なども格納することができます。

    (同上より)

    あぁ~、なんかややこしいなぁ。。 (+_+)

    Empty 値 とはヘルプによると、

    その変数が初期化されていないことを示し

    Null 値とは、

    その変数に有効なデータが格納されていないことを示します。

    確認しておく。

        Dim hoge As Variant
        
        Debug.Print IsNull(hoge)   ' False
        Debug.Print IsEmpty(hoge)  ' True
        
        hoge = Null
        
        Debug.Print IsNull(hoge)   ' True
        Debug.Print IsEmpty(hoge)  ' False
        
        hoge = 0
        
        Debug.Print IsEmpty(hoge)  ' False
        
        Set hoge = Nothing
        
        Debug.Print IsNull(hoge)   ' False
        Debug.Print IsEmpty(hoge)  ' False

    2009年5月13日水曜日

    VBA で文字列の配列の初期化

    1. 文字列の配列

    VBA で文字列の配列を初期化しようと思い、次のコードを実行した。

    dim strAry as String = {"hoge", "piyo", "fuga"}

    しかし、エラーが表示された。(@_@;) VB6 ってこういうのできなかったかな?

    VB 配列の初期化 によると、

    VB6では配列を初期化することはできません。要素ごとに値をセットする必要があります。ただし、固定長の配列は既定値で初期化されています。

    ちなみに .NET では上記のように書けるようだ。

    仕方がないので、

        Dim strAry(2) As String
        strAry(0) = "hoge"
        strAry(1) = "piyo"
        strAry(2) = "fuga"

    しかし、これは面倒だなぁ。。 (+_+)

     

    2. split 関数で初期化

    VB 文字列操作 に split 関数を使う方法が書かれていた。これを参考にして、

        Dim strAry() As String
        strAry = Split("hoge,piyo,fuga", ",")

    こちらの方が楽。 ^^

    VBA で文法のチェックをやめさせる

    Visual Basic Editor で VBA を書いているとき、文法を間違えるとすぐにエラーメッセージが表示される。if 文で条件をキチンと書く前に中の処理を書きたいときなど、一々注意されるのでうざい。 (+_+)

    そこで、メニューより 「ツール > オプション」より「編集 > コードの設定」の「自動構文チェック」のチェックをはずした。

    090513-003.png

     

    これで意図的に文法に不備があった場合でも、エラー箇所が赤く表示されるだけでエラーメッセージが表示されなくなったので、ちょっと書きやすくなった。

    090513-004.png

    2009年5月11日月曜日

    ノートPC が無線LAN に接続できない場合、ドライバを更新する

    無線LAN が原因でブルースクリーンになる

    ノート PC で無線LAN を利用すると最近調子が悪い。無線LAN の設定を WEP から WPA へ 変更してからくらいだろうか ?

    症状は、一度休止状態にすると、起こした後、何度か無線LAN に手動で接続しないとつながらない。ひどいときは 4, 5 回 接続接続… と繰り返し。

    しかも、なぜか頻繁にブルースクリーンになることが。 (@_@;)

    エラーの内容は、

    DRIVE_IRQL_NOT_LESS_OR_EQUAL

    それに ar5211.sys が絡んでいるらしい。

    別の PC で、同様の症状に対する説明があった。 

    ar5211.sys が原因でブルースクリーン上にSTOPエラーメッセージが表示されると共にシステムが応答しなくなったり、またはエラーメッセージの後システムが再起動する場合があります

    (Lenovo 以前のバージョンのIBM ワイヤレス LAN Mini PCI アダプター ソフトウェアが原因でシステムがハングアップ(XPクラッシュ)または再起動することがある より)

    どうやら 無線LAN が怪しそうだ。

     

    ドライバを更新したら、問題なくなった

    • コントロールパネル > 管理ツール > コンピュータの管理 > デバイスマネージャ

    のネットワークアダプタより、このノート PC で 無線LAN を使用するための `ATHEROS AR5002G’ のドライバの

    「日付」

    を見ると、結構古いものが使われていた。

    より、AR5002G の WXP 32bit をダウンロードして、ドライバの更新を行った。

    結果、何の問題もなくなった。 ^^

    2009年5月8日金曜日

    Blogger に投稿した記事をエディタで編集する – Firefox のアドオン It’s All Text! を使って

    1. ブラウザの画面でブログを編集するには限界がある

    090508-030Windows Live Writer で Blogger に投稿した記事を編集する場合、 過去に遡れる記事の限界は 500 までとなる。 500 個の記事を取得するにはかなり時間がかかる。

    もし、全ての記事を Windows Live Writer 行なっているのなら、投稿した記事を管理しているフォルダから見つければいい

    そうでなければ、ブラウザから直接修正する必要がある。ブラウザで記事を編集する際、Stylish で Blogger の投稿画面を広げればある程度文字の入力がしやすくなる。しかし、HTML で編集したい場合、ブラウザの画面では限界がある。

    2. It’s All Text! を使いエディタでテキストエリアを編集する

    Firefox のアドオン It's All Text! を利用すると、テキストエリアを好きなエディタで編集できるようになる。

    ここではエディタとして Aptana を使った。当初、サクラエディタ で編集しようとしたが、HTML を整形し、タグの補完をしてほしかったので Aptana を使った。

     

    a. エディタの設定

    設定はアドオンの It’s All Text! よりエディタを指定する。

    デフォルトではテキストエリアの内容が .txt として開かれる。HTML ファイルとして編集したい場合は、ファイル拡張子において .html を先頭に記述する。

    090508-026

    b. 使い方
    Blogger で投稿内容を HTML で編集したい場合、記事を編集状態にし、テキストエリアに内容を表示する。記事を 「HTML の編集」で開き、右下に表示される「編集」をクリックすることで Aptana が起動する。

    090508-031.png
    Aptana でコードを整形するには、Ctrl + Shift + F を押す。タグの補完は自動的に行なわれるので便利。090508-032.png Run ボタンを押せば、記述した内容を外部のブラウザで確認できる。 起動が遅いことだけが玉に瑕。(+_+)

     

    関連記事

    2009年5月7日木曜日

    Excel の VBA でグラフの対象範囲を更新する

    1. グラフの内容を、データ入力に応じて変化させたい

    Excel でデータから、グラフを作成。グラフをワークシートに埋め込んだとする。

    090506-019

    このグラフをデータの入力応じて変化するようにしたい。

    このために、グラフの範囲設定に OFFSET 関数を入力してみたけれど、できなかった。

    OFFSET の具体的な結果が設定され、値が固定されてしまう。 (+_+)

     

    2. マクロで記録したものを改造

    そこで、マクロで、グラフの対象範囲を変更する操作を記録してみた。

    Sub Macro1()
        ActiveSheet.ChartObjects("グラフ 1").Activate
        ActiveChart.ChartArea.Select
        ActiveChart.SetSourceData Source:=Sheets("Sheet1").Range("A1:C10")
    End Sub

    これを元にして、ワークシートに埋め込まれたグラフを更新する関数を作成。

    ' ワークシートに埋め込まれたグラフを更新する
    Sub SetChartObjectRange(strWorksheet As String, strChart As String, strRange As String)
        Worksheets(strWorksheet).ChartObjects(strChart).Activate
        ActiveChart.SetSourceData Source:=Sheets(strWorksheet).Range(strRange)
    End Sub

    呼出すときは、グラフが埋め込まれたシート名、グラフ名、範囲を文字列を引数に指定する。

    SetChartObjectRange "Sheet1", "グラフ 1", "A1:c10"

    ところで、グラフをアクティブにしてないと上記はエラーになる。アクティブにしないで更新する方法はないのかなぁ?

     

    3. Excel におけるオブジェクト

    上記 ChartObject オブジェクト とは、

    ワークシートにある埋め込みグラフを表します。ChartObject オブジェクトは、Chart オブジェクトのコンテナとして機能します。(ヘルプより)

    これに対して Chart オブジェクト というのもあったが、これは、

    ブック内のグラフを表します (ヘルプより)

    つまり、Chart オブジェクトは埋め込みではなく、一つのシートで一面グラフのもの (グラフシート) を表わすようだ。

    ちなみによく使う Worksheet オブジェクト は、

    ワークシートを表します。(ヘルプより)

    当り前か。 ^^;

    Excel のオブジェクトモデルを見ていたら、名前がよく似た Sheets コレクション オブジェクト というのがあった。

    指定されたブックまたは作業中のブックにあるすべてのシートのコレクションです。Sheets コレクションには、Chart オブジェクトまたは Worksheet オブジェクトを含めることができます。(ヘルプより)

    Workbook オブジェクト は、

    Excel ブックを表します。Workbook オブジェクトは Workbooks コレクションのメンバーです。Workbooks コレクションには、現在開かれているすべての Workbook オブジェクトが含まれています。(ヘルプより)

    そして、最上位には Application オブジェクトがある。これをまとめて図にすると、

     

    4. グラフシートの範囲を設定

    Chart オブジェクトを更新するには、

    ' グラフシートを更新する
    Sub SetChartRange(strChart As String, strWorksheet As String, strRange As String)
        Charts(strChart).Activate
        ActiveChart.SetSourceData Source:=Sheets(strWorksheet).Range(strRange)
    End Sub

    呼出すときは、グラフシート名, グラフの対象のシート名, 範囲を文字列で指定する。

    SetChartRange "Graph1", "Sheet1", "A1:c10"

    上記 Charts コレクション とは、

    指定されたブックまたは作業中のブックにあるすべてのグラフ シートのコレクションです。各グラフ シートは、Chart オブジェクトによって表されます。ワークシートまたはダイアログ シートにある埋め込みグラフは含まれません。

    Charts(“グラフチャート名”), Worksheets(“ワークシート名”) というように、コレクションに対して文字列でその要素を指定するというのがパターンのようだ。これは Access で Forms(“フォーム名”) と指定するのと同じ。

     

    5. グラフの対象となるワークシートの最後の行番号を知りたい

    No.8 ワークシートの最終行、最終列を取得する」によると、

    UsedRangeプロパティは指定されたワークシートで使われたセル範囲を返します

    これを利用して、ワークシートで使われている範囲のアドレスを文字列で取得。それを先ほど定義した埋め込み用のグラフの範囲を設定するプロシージャに渡す。

    SetChartObjectRange "Sheet1", "グラフ 1", Worksheets("Sheet1").UsedRange.Address

    しかし、これだと離れた列を対象とした、以下のグラフを作成できない。

    090507-023

    最後の行番号を取得できた方が、柔軟に対応できそう。Address プロパティで取得した文字列から行番号を抽出することにした。

     

    6. 正規表現を利用

    Office TANAKA - Excel VBA(正規表現によるマッチング) によると、

    VBAから正規表現を使うには、VBScriptが便利です。ただし、正規表現をサポートしているVBScriptはVer5.0からですから、IE5.0がインストールされているパソコンでないと使えません。

    また、正規表現における後方参照は、VBAで正規表現 - へたれプログラマな日々 を参考にした。

    ワークシート名を渡されると、使われている最後の行番号を返す関数を定義する。

    Function LastRowNum(strWorksheet As String)
        Set re = CreateObject("VBScript.RegExp")
        strCellAddress = Worksheets(strWorksheet).UsedRange.Address(RowAbsolute:=False, ColumnAbsolute:=False)
        re.Pattern = "[A-Z]+[0-9]+:[A-Z]+([0-9]+)"
        LastRowNum = re.Replace(strCellAddress, "$1")
    End Function

    これで例えば、上記のグラフの範囲を設定するなら、

        rownum = LastRowNum("Sheet1")
        SetChartObjectRange "Sheet1", "グラフ 1", "A1:A" & rownum & ",C1:C" & rownum

     

    7. 全体

    ' ワークシートに埋め込まれたグラフの範囲を更新する
    Sub SetChartObjectRange(strWorksheet As String, strChart As String, strRange As String)
        Worksheets(strWorksheet).ChartObjects(strChart).Activate
        ActiveChart.SetSourceData Source:=Sheets(strWorksheet).Range(strRange)
    End Sub
    
    ' グラフシートの範囲を更新する
    Sub SetChartRange(strChart As String, strWorksheet As String, strRange As String)
        Charts(strChart).Activate
        ActiveChart.SetSourceData Source:=Sheets(strWorksheet).Range(strRange)
    End Sub
    
    ' ワークシートの使われている最後の行番号を返す
    Function LastRowNum(strWorksheet As String)
        Set re = CreateObject("VBScript.RegExp")
        strCellAddress = Worksheets(strWorksheet).UsedRange.Address(RowAbsolute:=False, ColumnAbsolute:=False)
        re.Pattern = "[A-Z]+[0-9]+:[A-Z]+([0-9]+)"
        LastRowNum = re.Replace(strCellAddress, "$1")
    End Function
    
    Sub UpdateGraph()
        rownum = LastRowNum("Sheet1")
        SetChartObjectRange "Sheet1", "グラフ 1", "A1:A" & rownum & ",C1:C" & rownum
    End Sub

    Dropbox で友人とファイル共有

    Dropbox は既になくてはならないサービスの一つになった。

    これまでは自分一人で使うことしかしてこなかったが、今回はファイル共有するために使ってみる。てゆうか、この機能あることに使うまで気がつかなくて、別のサービス探してた。^^;

     

    方法

    Dropbox の Home にアクセスする。

    Share のリンクをクリックして、設定画面で共有したいフォルダ名と、共有したい人のメールアドレスを入力して Share folder ボタンをクリック。

     

    090506-021

    マイドキュメント > My Dropbox に 090506-020共有していることを示すアイコンが表示される。招待された人は Accept するだけ。

    あぁ~ Dropbox って本当にお手軽で便利だなぁ ^^

    2009年5月6日水曜日

    表計算で入力に応じて計算の範囲を変化させる - 「範囲を返す」 OFFSET 関数と「データ数を数える」 COUNT 関数を用いて

    1. 入力に応じて計算対象の範囲を指定したい

    090505-015例えば、A 列に「テストの得点」を入力する列がある。

    テストの得点は、下方向へ入力していく。この入力に応じて「平均」を計算するための「範囲」が変化し、計算が行われるようにしたい。

    平均を計算するとき、以下のように列まるごと対象にした式を書くことはできる。

    =AVERAGE(A:A)

    ここでは、列全体を AVERAGE 関数に与えるのではなく、入力された範囲を引数に与えるようにしたい。

     

    2. COUNT 関数でデータ数を得る

    最初に、データ数をカウントするための

    • COUNT 関数

    について確認する。Excel のヘルプによると、

  • COUNT 関数では、数値、日付、数値を表す文字列が計算の対象となります。エラー値、数値に変換できない文字列は無視されます
  • 090505-015よって、A 列にあるデータ数を得るには、

    =COUNT(A:A)

    このとき、先頭の見出しの文字列はカウントされない。

    D2 セルに上記の式を記述し、そのセルを「データ数」と名付けた。

     

    3. OFFSET 関数で計算対象の「範囲」を得る

    次に、計算対象の「範囲」を取得する。そのためには、OFFSET 関数を利用する。

    OFFSET の意味は、オフセットとは 【offset】 - 意味・解説 : IT用語辞典 によると、

    あるデータの位置を、基準点からの差(距離)で表した値のこと。

    この意味からは、範囲を返す関数であることは分からない。関数の名前が良くないと思う。

    Excel のヘルプによると、

    基準のセルまたはセル範囲から指定された行数列数だけシフトした位置にある高さのセルまたはセル範囲の参照 (オフセット参照) を返します。

    使い方は 「[XL2002] OFFSET 関数の使用方法」 を参照。

    OFFSET 関数の引数をイメージしやすいように図にしておく。

    090506-017

    表は、基本的に「行 → 列」という順序で考えるのが普通。よって、引数の並びとして、「行数」「列数」が並んでいるので覚えやすい。「高さ」「幅」というのは、言い換えれば、「対象となる行のデータ」と「対象となる列のデータ」ということ。これも「行 → 列」という順序に並んでいると見なせる。

    今回は OFFSET の意味に相当する引数「行数、列数」は考えない。必要なのは、基準となるセルとそこからの範囲指定を行うための「高さ」と「幅」。

    OFFSET 関数を適用する前に、セル A2 を「データの先頭」と名付けた。平均を計算するため、セル D3 に次のように記述。

    =AVERAGE(OFFSET(データの先頭,0,0,データ数,1))

    090505-014

     

    セルに名前を付けず、途中の計算も書かないで書くなら、

    =AVERAGE(OFFSET(A2,0,0,COUNT(A:A),1))

    となる。

    2009年5月5日火曜日

    Gimp でパスの操作 – つなげる・分割する

    パスを新しく開始

    PathsTool パスツールでパスを作成していて、パスをつなげずに新しくパスを開始したいときは、Shift キーを押しながらクリックする。

    090505-012

     

    つなげる

    後で離れたところをつなげたくなったら、

    1. つなげたいパスの点の片方をクリック
    2. もう片方を Ctrl キーを押しながらクリック

    090505-013

     

    削除・分割

    パスの点を削除したい場合は、Ctrl を押しながら Delete キーを押す。

    もしくは Ctrl + Shift キーを押しながらパスの点をクリック。この場合、パスの線をクリックするとその線が消えパスが分割される。Ctrl + クリックでパスの点を追加できるので、分割したいところを拡大して二つ点を追加し、その間の線を削除するとよい。

     

    オプション

    わからなくなったら、PathsTool パスツールのアイコンをダブルクリックしてオプションを表示させる。Edit Mode の Edit に (Ctrl)

    090505-008

    Excel の VBA で名前を付けたセルの内容を参照

    特定の範囲に名前を付ける

    一つのセル、または、特定の範囲に名前を付けるには、セルを選択した後にワークシートの左上をクリックして名前を入力する。

    例えば、セルA1 に “hoge” と名前を付けてみた。

    090505-005

     

    付けた名前を管理しているのは、メニューより「挿入 > 名前 > 定義」。ここで定義した名前を追加・削除できる。

    先ほど定義した “hoge” が表示されている。

    090505-006

    ちなみに、ワークシートごとに名前空間があるのではなく、一つの Excel ファイルにおいて一意な名前を付けることができるようだ。

     

    VBA で名前を付けたセルの値を参照

    メニューより「ツール > マクロ > Visual Basic Editor」を選択し、標準モジュールを作成。(「挿入 > 標準モジュール」)

    さて、セルの値を参照するにはどうすればいいのだろう? Visual Basic Editor 内において F1 でヘルプを表示し、「Microsoft Office Excel オブジェクト モデル」を見ると、Cell というのは見当たらず。

    ところで、上記のように名前を付けるとき、範囲を指定して名前を付けることができた。ということは Range で操作できそうだ。

    090505-007

    ヘルプの Range コレクションによると、

    セル、行、列、1 つ以上のセル範囲を含む選択範囲、または 3-D 範囲を表します。

    標準モジュールにプロシージャを定義した。

    Sub test()
        MsgBox Range("hoge").Value
    End Sub

    プロシージャ内で、F5 または F8 を押して動作を確認。

     

    ちなみにセルを表わすものは、Worksheets オブジェクトのプロパティとして表現されていた。