2008-05-25  Excel VBAでブログに投稿する

XML-RPCを使うとExcelやAccessからブログに記事を投稿したり,修正したりすることができます。手順をご説明します。

概要

注意事項

現在のvbXMLRPC.dll(Ver.0.9.0042)は,DBCS(Double Byte Character Set)に対応していないようです。どういう意味なのかというと,日本語を含む文字列を送受信させるとエラーになります。

「それじゃだめじゃん」ということになるのですが,裏技があるのです。日本語をすべて数値文字参照(&#xxxx;という形式)に置き換えてしまえば,日本語を通すことができます。

投稿された文章は,普通のWWWブラウザであれば問題なく表示されるのですが,携帯電話では文字化けするかもしれません。また,投稿される文章の中身は「&#xxxx;」という記号の羅列です。ブログの管理画面で再編集しようとしたときに,はっきり言って読めませんので途方に暮れることになるかと思います。

これらを考慮した上で以下を読み進めてください。

準備

(1) vbXMLRPC.dllのインストール

vbXMLRPC Binaries Download」からダウンロードのページに進んで,vbXMLRPCのバイナリをダウンロードします(発電所の画像が出てくるかもしれませんが,気にしないでください)。ZIPファイルを「c:\program files\」以下に解凍しておきましょう。

(2) 参照設定

vbXMLRPCをVBAで使うための設定です。

(i) Excelを起動し「Visual Basic Editor」を起動します。

(ii) <Excel 2007を使っていてVisual Basic Editorの起動方法が分からない場合>Excel 2007ではリボンの「開発」タブから起動することができます。「開発」タブはExcelの標準設定では表示されません。Excelのオプションを開き,「[開発]タブをリボンに表示する」をチェックしておきます。<画像↓>

Excelのオプション

(iii) Visual Basic Editorの「ツール(T)→参照設定(R)」にて,参照設定ダイアログを開きます。「参照(B)」ボタンをクリックし,vbXMLRPC.dllを選択します。

(iv) 「vbXML - Simple XML Parser」と「vbXMLRPC - XML-RPC Client」の2項目をチェックし,OKをクリックします。<画像↓>

参照設定

(3) ブログの設定

以下の4点を調べておきましょう。

確認の仕方はお使いのブログによって異なります。また(当然のことですが)XMLRPCに対応していないブログでは使えません。

コード

以下,metaWeblog.newPostのサンプルコードです。実行すると少し待たされます。投稿時にブログが再構築されるからだと思います。ブログの設定を変えれば挙動が変わるのかもしれません。

Public Sub newPost()

  Dim linsRequest As New XMLRPCRequest
  Dim linsResponse As XMLRPCResponse
  Dim linsUtility As New XMLRPCUtility
  Dim linsStruct As New XMLRPCStruct

  linsRequest.HostName = "blog.sakura.ne.jp" ' ホスト名
  linsRequest.HostPort = 80 ' ポート番号

  linsRequest.HostURI = "/rpc/" ' パス
  linsRequest.MethodName = "metaWeblog.newPost"

  linsRequest.params.AddString "12345678" ' ブログID
  linsRequest.params.AddString "example.sakura.ne.jp" ' ユーザ名
  linsRequest.params.AddString "password" ' パスワード

  '
  linsStruct.AddString "title", HTMLEntity_encode("タイトル")
  linsStruct.AddString "description", HTMLEntity_encode("本文")
  linsStruct.AddString "dateCreated", "2007-04-01T00:00:00"

  linsRequest.params.AddStruct linsStruct ' content
  linsRequest.params.AddBoolean True ' publish

  Set linsResponse = linsRequest.Submit

  If linsResponse.STATUS = XMLRPC_PARAMSRETURNED Then

    ' リクエストが成功すると記事IDが返ってくる
    Debug.Print "id=" & linsResponse.params(1).StringValue

  Else

    Select Case linsResponse.STATUS

    Case XMLRPC_PARAMSRETURNED
      Debug.Print "Unexpected response from XML-RPC request " & linsResponse.STATUS
    Case XMLRPC_FAULTRETURNED
      Debug.Print "Server returned a fault. Code is '" & linsResponse.Fault.FaultCode
      & "', description is '" & linsResponse.Fault.FaultString & "'."
    Case XMLRPC_HTTPERROR
      Debug.Print "HTTP error encountered. Code is '" & linsResponse.HTTPStatusCode
      & "', description is '"& linsUtility.GetHTTPError(linsResponse.HTTPStatusCode) & "'."
    Case XMLRPC_XMLPARSERERROR
      Debug.Print "XML Parsing Error encountered '" & linsResponse.XMLParseError & "'."
    Case XMLRPC_NOTINITIALISED
      Debug.Print "Weird, the response claims not to be initialised !!!"
    Case Else
      Debug.Print "Double Weird, unknown response status '" & linsResponse.STATUS & "'."

    End Select

  End If

End Sub

Public Function HTMLEntity_encode(str As String) As String

  Dim ret As String
  ret = ""

  Dim i As Long
  Dim c As String
  Dim charCode As Integer
  Dim hexCode As String

  For i = 1 To Len(str)
  
    c = Mid(str, i, 1)
    charCode = AscW(c)
    
    If charCode > 127 Then
    
      hexCode = Hex(charCode)
      ret = ret & "&#x" & hexCode & ";"
    
    Else
    
      ret = ret & c
    
    End If
  
  Next

  HTMLEntity_encode = ret

End Function

メモ

いずれにしても何か分かったことがあったら,お知らせします。

ExcelとAccessどちらが良いのか

ExcelとAccessのどちらを使えばよいのか悩む人がいるかもしれません。なぜなら,今回のお題はExcelとAccessのどちらからでもできるのです。

Accessではデータに項目(フィールド)とデータ型を指定できますので,データ構造が堅牢になります。操作の不手際で,変なデータになってしまう危険性を低くすることができます。また項目には名前をつけることができるので,VBAの入力補完機能を利用して項目名を入力できるという利点もあります。「できる」ことがたくさんあるというわけですね。

対してExcelですが,仕事を早く片付けたい場合や職場で複数の人と作業している場合には魅力的な選択肢でしょう。「最適」とは言えないものの, Office付きのPCであれば必ずインストールされていますので入手しやすいです。また書籍やネットで入手できる情報量は,Excelの方が多いようです。

Excelであれば「困ったとき」に,だれかが助けてくれる可能性が高いと考えられるのです。

»固定リンク

2007-11-03  Excel VBAで実体参照のエンコードとデコード

Excel VBAでHTMLの実体参照をエンコード・デコードするコードを作りました。コードそのものはVB6.0処理系汎用であり,Excel VBA以外でも使えると思います。

あらまし

「HTMLの実体参照」とは,HTMLのメタ文字をエスケープするための記述方法です。メタ文字とは,「タグ」を書くときに使う文字です(正確にはちょっと違うけど)。たとえば「<>」を書きたいときは,「&lt; &gt; 」と書かなければいけません。「<>」はHTMLのメタ文字なので,これらを直接,書いてしまうと「タグ」と区別がつかなくなってしまうのです。

Excelで実体参照の混ざった文字列を扱うことは,あまりないと思いますが,あまりないがために必要に迫られたとき困るのです。

動作概要

仕様

注意事項

コード(クラスモジュールHTMLEntity)

' require VBScript.RegExp, Scripting.Dictionary

Option Explicit

Private m_regex_encode As Object ' VBScript.RegExp
Private m_regex_decode As Object ' VBScript.RegExp
Private m_regex_decodehex As Object ' VBScript.RegExp
Private m_regex_decodedec As Object ' VBScript.RegExp

Private m_entity2char As Object ' Scripting.Dictionary
Private m_char2entity As Object ' Scripting.Dictionary

Private Function RegExp(pattern As String, Optional g As Boolean = False, _
                            Optional i As Boolean = False) As Object

    Set RegExp = CreateObject("VBScript.RegExp")

    With RegExp

        .pattern = pattern
        .Global = g
        .ignorecase = i

    End With

End Function

Private Sub Class_Initialize()

    Dim t As String
    Dim m As Object ' match
    Dim name As String
    Dim value As String

    Set m_regex_encode = RegExp("([""&<>])", g:=True)
    Set m_regex_decode = RegExp("&([\w#][\w\d]*);?", g:=True)
    Set m_regex_decodehex = RegExp("#[xX]([0-9a-fA-F]{1,4})")
    Set m_regex_decodedec = RegExp("#(\d{1,5})")

    Set m_entity2char = CreateObject("Scripting.Dictionary")
    Set m_char2entity = CreateObject("Scripting.Dictionary")

    ' ISO 8859-1
    t = "" _
        & "nbsp 160 iexcl 161 cent 162 pound 163 curren 164 " _
        & "yen 165 brvbar 166 sect 167 uml 168 copy 169 " _
        & "ordf 170 laquo 171 not 172 shy 173 reg 174 " _
        & "macr 175 deg 176 plusmn 177 sup2 178 sup3 179 " _
        & "acute 180 micro 181 para 182 middot 183 cedil 184 " _
        & "sup1 185 ordm 186 raquo 187 frac14 188 frac12 189 " _
        & "frac34 190 iquest 191 Agrave 192 Aacute 193 Acirc 194 " _
        & "Atilde 195 Auml 196 Aring 197 AElig 198 Ccedil 199 " _
        & "Egrave 200 Eacute 201 Ecirc 202 Euml 203 Igrave 204 " _
        & "Iacute 205 Icirc 206 Iuml 207 ETH 208 Ntilde 209 " _
        & "Ograve 210 Oacute 211 Ocirc 212 Otilde 213 Ouml 214 " _
        & "times 215 Oslash 216 Ugrave 217 Uacute 218 Ucirc 219 " _
        & "Uuml 220 Yacute 221 THORN 222 szlig 223 agrave 224 " _
        & "aacute 225 acirc 226 atilde 227 auml 228 aring 229 " _
        & "aelig 230 ccedil 231 egrave 232 eacute 233 ecirc 234 " _
        & "euml 235 igrave 236 iacute 237 icirc 238 iuml 239 " _
        & "eth 240 ntilde 241 ograve 242 oacute 243 ocirc 244 " _
        & "otilde 245 ouml 246 divide 247 oslash 248 ugrave 249 " _
        & "uacute 250 ucirc 251 uuml 252 yacute 253 thorn 254 " _
        & "yuml 255"

    ' Mathematical, Greek and Symbolic (1/2)
    t = t & " " _
        & "fnof 402 Alpha 913 Beta 914 Gamma 915 " _
        & "Delta 916 Epsilon 917 Zeta 918 Eta 919 Theta 920 " _
        & "Iota 921 Kappa 922 Lambda 923 Mu 924 Nu 925 " _
        & "Xi 926 Omicron 927 Pi 928 Rho 929 Sigma 931 " _
        & "Tau 932 Upsilon 933 Phi 934 Chi 935 Psi 936 " _
        & "Omega 937 alpha 945 beta 946 gamma 947 delta 948 " _
        & "epsilon 949 zeta 950 eta 951 theta 952 iota 953 " _
        & "kappa 954 lambda 955 mu 956 nu 957 xi 958 " _
        & "omicron 959 pi 960 rho 961 sigmaf 962 sigma 963 " _
        & "tau 964 upsilon 965 phi 966 chi 967 psi 968 " _
        & "omega 969 thetasym 977 upsih 978 piv 982 bull 8226 " _
        & "hellip 8230 prime 8242 Prime 8243 oline 8254 frasl 8260 " _
        & "weierp 8472 image 8465 real 8476 trade 8482 alefsym 8501 " _
        & "larr 8592 uarr 8593 rarr 8594 darr 8595 harr 8596 " _
        & "crarr 8629 lArr 8656 uArr 8657 rArr 8658 dArr 8659 " _
        & "hArr 8660 forall 8704 part 8706 exist 8707 empty 8709 " _
        & "nabla 8711 isin 8712 notin 8713 ni 8715 prod 8719 " _
        & "sum 8721 minus 8722 lowast 8727 radic 8730 prop 8733 " _
        & "infin 8734 ang 8736 and 8743 or 8744 cap 8745 " _
        & "cup 8746 int 8747 there4 8756 sim 8764 cong 8773 " _
        & "asymp 8776 ne 8800 equiv 8801 le 8804 ge 8805 " _
        & "sub 8834 sup 8835 nsub 8836 sube 8838 supe 8839 " _
        & "oplus 8853 otimes 8855 perp 8869 sdot 8901 lceil 8968 "

    ' Mathematical, Greek and Symbolic (2/2)
    t = t & " " _
        & "loz 9674 spades 9824 clubs 9827 hearts 9829 diams 9830 " _
        & "rceil 8969 lfloor 8970 rfloor 8971 lang 9001 rang 9002 "

    ' Special
    t = t & " " _
        & "quot 34 amp 38 lt 60 gt 62 OElig 338 " _
        & "oelig 339 Scaron 352 scaron 353 Yuml 376 circ 710 " _
        & "tilde 732 ensp 8194 emsp 8195 thinsp 8201 zwnj 8204 " _
        & "zwj 8205 lrm 8206 rlm 8207 ndash 8211 mdash 8212 " _
        & "lsquo 8216 rsquo 8217 sbquo 8218 ldquo 8220 rdquo 8221 " _
        & "bdquo 8222 dagger 8224 Dagger 8225 permil 8240 lsaquo 8249 " _
        & "rsaquo 8250 euro 8364"

    For Each m In RegExp("([\w][\w\d]*)\s(\d+)\s?", g:=True).Execute(t)

        name = m.submatches(0)
        value = ChrW(m.submatches(1))

        m_entity2char.Add name, value
        m_char2entity.Add value, name

    Next

End Sub

Public Function encode(s As String) As String

    Dim p As Integer
    Dim str As String
    Dim m As Object ' match

    p = 0
    str = ""

    For Each m In m_regex_encode.Execute(s)

        If p < m.firstindex Then

            str = str & Mid(s, p + 1, m.firstindex - p)

        End If

        str = str & "&" & m_char2entity.Item(m.submatches(0)) & ";"

        p = m.firstindex + m.Length

    Next

    str = str & Mid(s, p + 1)

    encode = str

End Function

Public Function decode(s As String) As String

    Dim p As Integer
    Dim str As String
    Dim m As Object ' match
    Dim c As String

    p = 0
    str = ""

    For Each m In m_regex_decode.Execute(s)

        c = m.submatches(0)

        If p < m.firstindex Then

            ' 実体参照が現れる位置までの文字列をコピーする
            str = str & Mid(s, p + 1, m.firstindex - p)

        End If

        If m_entity2char.Exists(c) Then

            ' 文字実体参照
            str = str & m_entity2char.Item(c)

        Else

            With m_regex_decodehex.Execute(c)

                If .Count Then

                    ' 数値文字参照16進
                    str = str & Chr(val("&h" & .Item(0).submatches(0)))

                Else

                    With m_regex_decodedec.Execute(c)

                        If .Count Then

                            ' 数値文字参照10進
                            str = str & Chr(.Item(0).submatches(0))

                        Else

                            ' 文字実体参照でも数値文字参照でもない
                            str = str & c

                        End If

                    End With

                End If

            End With

        End If

        p = m.firstindex + m.Length

    Next

    str = str & Mid(s, p + 1)

    decode = str

End Function

'EOF

Dim o As New HTMLEntity

Debug.Print o.decode("&amp;")
Debug.Print o.decode("&amp;&quot;&lt;&gt;")
Debug.Print o.decode("A&amp;")
Debug.Print o.decode("A&amp;B")
Debug.Print o.decode("&amp;B")
Debug.Print o.decode("&#x41;&#x42;&#x43;")
Debug.Print o.decode("&#65;&#66;&#67;")
Debug.Print o.decode("ABC") ' 実体参照を含まない
Debug.Print o.decode("&dagger;&Dagger;") '
Debug.Print o.decode("A&ampB") ' 末尾に「;」がない
Debug.Print o.decode("あいうえ") ' 日本語
Debug.Print o.decode("あ&amp;い") ' 日本語
Debug.Print o.decode("あ&ampい") ' 末尾に「;」がない
Debug.Print
Debug.Print o.encode("&")
Debug.Print o.encode("&""<>")
Debug.Print o.encode("A&")
Debug.Print o.encode("A&B")
Debug.Print o.encode("&B")
Debug.Print o.encode("ABC")

例の実行結果

実行結果

ほかの方法

おそらく専ら問題になるのはデコードだと思います。正規表現を使わない方法となると,実体参照の種類だけReplace関数を実行するしかないように思えます。性能面でかなり問題が出るのではないでしょうか。

BASICって,そもそも文字列処理が得意ではない気がするので,あまり無理をすると不幸になる可能性が大です。どこからか実体参照を扱うCOMを調達した方がよいでしょう。

関連リンク

»固定リンク

2006-10-01  Excel VBA漂流記の構築を開始しました

「Excel VBA漂流記」はExcel VBAをいじっていて,困ったり奇妙だなと思ったりしたことを書き綴ったサイトです。

計画当初,Microsoft Officeの新しいバージョンの動向がよく分かりませんでした。「作ってもだれも見ないのでは」という恐れがありました。Office12でもVBAは存続するそうですので,決行することにしました。

独自色を出すのが難しい

サイトの方向性を考えることにします。

この手の「ちょっとしたメモ」のサイトはいくつかあります。無数というほど沢山ではありませんが,すでに似たような情報を公開している人は大勢いるのです。

求められているのは,市販されている書籍には載っていない情報だと考えられます。たとえば仕様にはない動作に関する情報。立場により人はその動作を「バグ」と言ったり,「実装仕様」と言ったりします。

またたいていの書籍は機能の断片と,ごく小規模なアプリケーションの説明しかしていません。もともとVBAの用途はExcelの機能をちょっとだけ拡張するというもののようですので,当然といえば当然なのです。

さて昨今のプロセッサの処理能力の向上により,わりと大きなアプリケーションも動かせるようになってきました。ところが小物以上のアプリケーションをどうやって作るのか,といった情報はほとんど見かけません。

そこでExcel VBA漂流記では,以下の二点に重点を置くことにします。

あくまで「目標」なので,必ずこのとおりにするというわけではありません。

CMSにYukiWikiを使用

ただいまYukiWikiで実装検証をしています。

Wikiの詳しい説明は省略しますが,普通Wikiでは不特定多数の人が自由に内容を書き換えることができます。

Wikiはイタズラされ放題です。仮にイタズラされることがあっても「澱みは自然に浄化される」という発想なのですが,浄化されるのは流れのある箇所だけです。滅多に見ないようなページは,澱んだままになってしまう危険があるのです。

またWikiを狙ったSPAMも出てきているらしく,まったくもって予断を許しません。

作業計画

  1. 方針作成
  2. 内容検討
  3. 方式検討 ← 【いまここ】
  4. 構造決定
  5. ローカルサーバ構築
  6. 仮データ作成
  7. リモートサーバ構築
  8. データ移植
  9. 正式公開

「正式公開は11月末日あたりに」と思っていますが,どうなることやら。

»固定リンク

2006-03-06  Excel X for MacでChartオブジェクトのExportメソッドが機能しない

※「Excel VBA漂流記:Macintoshプラットフォーム固有の問題」でまとめるつもりでしたが,小出しにすることにしました。

現象

Excel X for MacでChartオブジェクトのExportメソッドを使って,グラフを画像ファイルにしようとしたら「実行時エラー’1004’:’Export’メソッドは失敗しました : ‘_Chart’ オブジェクト」というエラーが発生してしまいました。

おそらく回避できない問題

Excel X for Mac(Office v. X for Mac)ではChartオブジェクトのExportメソッドは使用不可のようです。Office v. X for Macはエクスポート用のグラフィックフィルタをひとつも持っていないからです。

この問題を回避・代替する方法はたぶんありません。

Office v. X for Macのグラフィックフィルタ

オンラインヘルプにてExportメソッドを調べてみると,有効なFilterNameの例は「GIF,JPEG,PNG」だとしています。さらに「Macintoshではエクスポート用のグラフィックフィルタは,Microsoft Office X/Shared Applications/Graphic Filtersフォルダにある」と書かれています。

実際に「Macintosh HD:Microsoft Office X:Shared Applications:Graphic Filters:」を開いてみたところ,「EPS Import」と「Metafile Import」というふたつのグラフィックフィルタが存在していました。

名前を信用すると,これらのグラフィックフィルタはインポートのみでエクスポートする機能はありません。

メモ

リンク

»固定リンク

2005-12-19  Visual Basic6.0処理系の感想

Visual Basic6.0処理系(以下VBと表記)を使い始めて5か月ほどが経過しました。だいたい使えるようになったので感想をお話します。

【注意】実際に使っていたものはExcel VBAです。細かい説明をすると長くなるのでVBA≒VB6.0とお考えください。なおVB.NETは別ものなのであしからず。

VBは遅いか

巷では「VBは遅い」であるとか「VBで出来たソフトは不出来」という評判をよく耳にします。さらには「VBでソフトを作っている人間は無能」という乱暴な意見すら散見されます。確かにVBで作られたフリーソフトや業務用アプリケーションの中には反応が鈍かったり,画面の描画が欠けたりするものが存在します。

私はVBがインタプリタなのと,紛いにもBASICなので「遅くて使い物にならないのでは」と懸念していました。

実際に使ってみると,計算量のオーダーをきちんと意識して設計すれば遅くなりませんでしたし,システムに再描画の機会を適切に与えれば画面がおかしくなることもありませんでした。たとえば大量のレコードを探索するときは,ハッシュテーブルを使って計算量を減らす工夫をすれば実時間で処理が終わります。

いまどきのプロセッサはとんでもなく速いので,インタプリタだからといって支障が出るほど遅いなんてことはないのです。

関数ポインタの代替方法

VBにはポインタがありません。ポインタ型そのものはありませんが,オブジェクトの変数は暗黙で参照型ですし,プリミティブ型をサブルーチンやメソッドの引数に使う場合は値渡しと参照渡しを選ぶことができます。

「うーむ」と考え込んでしまったのは,関数ポインタ(実行コードの位置を指し示す)が使えないことでした。

並び替えのサブルーチンがあったとして,順序を返す関数をどうやって実装するのかちょっと悩みました。ところで関数ポインタが存在しないのはJavaも同じです。

Javaではインターフェイスにコールバックさせるメソッドを定義して,呼び出し元にはインターフェイスを実装したオブジェクトの参照を持たせるのが常套手段です。

VBも同じ発想でコールバックが実現できます。

例外処理

いちばん気になったのは例外処理です。VBにはtry-catch-finally構文が存在しないので,これに替わる手段を使わなければなりません。

try-catchの代替には「On error resume next」とif文による条件分岐を使います。VBにはシングルトンのErrオブジェクトというものがあり,エラーが発生するとErr.number属性にエラー値が代入されます。たとえばサブルーチンを呼び出した直後にif文でErr.numberの値を判定して,0以外であればサブルーチン内でエラーが発生したということになるのです。

私はfinallyの美しい換言案をまだ発見していません。ファイルを開いたときは,処理が成功しようが失敗しようが,途中でサブルーチンから抜けようがとにかく最後にはファイルを閉じたいということがよくあります。そんなときはfinallyの中でファイルを閉じておけば確実なのですが,VBではできないのです。

もちろんファイルを開いた後の処理を別のサブルーチンにしておいて,サブルーチンから抜けたらファイルを閉じる,という構造にすればfinallyの替わりにできそうです。でもこういう書き方は悪文になると思います。

»固定リンク

2005-11-20  Excel VBAの本の感想をまとめて

「サラサーティ1」の開発に際して,Microsoft Excelについてさまざまな調査をしました。今回の取り組みではExcel VBA(Visual Basic for Applications)を初めて使ったので,Visual Basicの文法からExcelのオブジェクトモデル,既知の問題まで幅広く情報収集しなければなりませんでした。

情報収集の際に何度も本屋さんに足を運びました。今日は市販されているExcelとVBAの書籍の感想をお話します。

EXCEL VBA コーディング・テクニック

(間 顕次著,毎日コミュニケーションズ,2002.8,ISBN 4-8399-0739-0)

初めて買った本です。最初はどんな本を選べば良いのかさっぱり分からなかったので,適当に買ってしまいました。

この本は買うだけ無駄のようです。例題はかなり実践的なのですが,「フォームにコントロール(GUI部品)をべたべた貼ってみました」という世界からの展開がありません。小物以上のマクロを作りたい人にとっては物足りないのです。

ここが知りたかった! Excel VBA 500の技

(Windowsプログラミング愛好会 著,技術評論社,2005.6,ISBN 4-7741-2414-1)

網羅性は高いのだが,極端に底が浅いです。分からないことを解決する糸口を見つけるのには役に立ちますが,決して糸は解けません。

Excel VBAの機能はものすごく多いので,どんな機能があるのか大雑把に知りたい人にとっては便利だと思います。

それから初版だからかもしれませんが,誤字・脱字がとても目立ちました。

Excel Hacks プロが教える究極のテクニック100選

(David Hawley,Raina Hawley著,羽山 博 監訳,2004.10,オライリー・ジャパン,ISBN 4-87311-205-2)

お勧めの一冊です。VBAとExcel数式を使った恐ろしい技がつぎつぎ出てきます。何気なく通りすぎて読み返してみると「おおっ」と来ます。

ただ完全性がないというか,柔軟性にやや欠ける気がしました。

例えば「勝手に広がる名前付き範囲」では,あらかじめ大雑把な行数をハードコード(直書き)しなければなりません。何ひとつ矛盾がなく,美しく整理された世界に焦れている人にとって数値が固定されているなんて,とても許されることではありません。

でも実際のExcelの利用現場を見ると,「阿漕」だとか「邪道」なんて言っている場合ではありません。「最終的にA4用紙からはみ出ないで印刷できればいい」というときには,数値が固定だろうが可変だろうが,セルの参照が絶対だろうが相対だろうが,そんなことはどうでいいのです。

経済・金融分析のためのVBAプログラミング

(原田 康平 著,牧野書店,2000.10,ISBN 4-7952-0136-6)

お勧めの一冊です。章立てがしっかりしており,学校で使う教科書みたいな書き方をしています。学術書に慣れている人にとってはかなり読みやすいと思います。

コンピュータ業界の人にとっては常識みたいな事柄も丁寧に書かれています。プログラミングの経験がまったくない人でも,自力で読み進めることができるでしょう。

ただこの本はお金の計算を目的としており,用途がかなり限定されます。また対象としているExcelのバージョンは「2000」ですので,やや古い感じがします。

Excelデータ分析[増補版]

(I/O編集部 著,工学社,2005.1,ISBN 4-7775-1096-4)

この本はVBAの本ではありません。Excelの統計関数を説明した本です。かなり平坦な言葉で書かれているので,統計の知識がなくても読むことができます。

数学の本って表記が難解というか「数式に使われている記号の意味すら分からない」なんて困ったことになりがちです。この本は,高校数学の知識があれば読めるように工夫されているらしく,極端な拒絶反応は起こりにくいようです。

»固定リンク

2005-09-09  Excel VBAで改行コードがLFのファイルを読む

Excel VBAで,CRLF以外の改行コードが含まれたテキストファイルを読み込むコードを作りました。

あらまし

VBAではLine Input # ステートメントを使うと,シーケンシャルファイルから1行ずつ読み込むことができます。

ところで,改行コードがLFのファイルを読み込ませてみたら,Excelが応答しなくなってしまいました。 Line Input # ステートメントは,改行コードがLFのファイルには対応していないようです。

そこでCRLF,LF,CRの三種類の改行コードに対応したコードを作ってみました。

動作概要

仕様

注意事項

コード

Const FILEBUFSIZE = 32767

Dim CR As String
CR = Chr(13)
#If Not Mac Then
    CR = StrConv(CR, vbFromUnicode)
#End If

Dim LF As String
LF = Chr(10)
#If Not Mac Then
    LF = StrConv(LF, vbFromUnicode)
#End If

Dim FileNum As Variant
FileNum = FreeFile()

Open "filename" For Binary Access Read As FileNum Len = FILEBUFSIZE

Dim byteBuf(FILEBUFSIZE - 1) As Byte
Dim strBuf As String
strBuf = ""

Dim FileSize As Long
FileSize = LOF(FileNum)

Do Until EOF(FileNum)

    Get FileNum, , byteBuf

    Dim SeekPoint As Long
    SeekPoint = Seek(FileNum) - 3

    If SeekPoint <= FileSize Then
        strBuf = strBuf & CStr(byteBuf)
    Else
        strBuf = strBuf & LeftB(CStr(byteBuf), FILEBUFSIZE - (SeekPoint - FileSize))
    End If

    Dim p1 As Long
    p1 = 0

    Dim p2 As Long
    p2 = 0

    Do
        p1 = InStrB(1, strBuf, CR, vbBinaryCompare)
        p2 = p1

        If p1 <> 0 Then

            If LenB(strBuf) < p1 + 1 Then
                p1 = 0
            ElseIf MidB(strBuf, p1 + 1, 1) = LF Then
                p2 = p2 + 1
            End If

        Else
           p1 = InStrB(1, strBuf, LF, vbBinaryCompare)
           p2 = p1
        End If

        If p1 = 0 And EOF(FileNum) And LenB(strBuf) > 0 Then
            p1 = LenB(strBuf)
            p2 = p1
        End If

        '

        If p1 <> 0 Then
            Dim head As String
            Dim tail As String

            head = MidB(strBuf, 1, p1 - 1)
            tail = MidB(strBuf, p2 + 1)

            #If Not Mac Then
                head = StrConv(head, vbUnicode)
            #End If

            Dim CurrentLine As String
            CurrentLine = head

            Debug.Print CurrentLine

            strBuf = tail
        End If

    Loop While p1 <> 0
Loop

Close FileNum

ほかの方法

(1) FileSystemObjectオブジェクトのReadLineメソッドも,改行コードLFに対応しているそうです(伝聞なので検証なし)。現在は,このFileSystemObjectオブジェクトを使う方法が主流なのかもしれません。

(2) Excelの機能である「外部データの取り込み」を使うと,シートに任意のテキストファイルを読み出すことができます。この機能では改行コードLFのファイルも読めます。VBAヘルプでQueryTablesオブジェクトを調べてみてください。

メモ

»固定リンク