2016年9月26日月曜日

ExcelからRSSを取得するサンプルプログラム

MSXMLを使用すれば、ExcelからRSSを取得できます。
XmlNode.SelectNodesメソッドを使用するときは名前空間(Namespace)に注意します。
サンプルではXMLDOMDocument.setPropertyを使用して名前空間を指定しています。

以下、サンプルプログラムです。

Public Sub Msxml()

    Dim namespaces As String
    Dim xml        As Object
    Dim ret        As Boolean
    Dim nodeList   As Object
    Dim item       As Object
    
    namespaces = "xmlns:rss='http://purl.org/rss/1.0/'"
    namespaces = namespaces + " xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'"
    
    Set xml = CreateObject("MSXML2.DOMDocument.6.0")
    Call xml.setProperty("ServerHTTPRequest", True)
    Call xml.setProperty("SelectionNamespaces", namespaces)
    xml.async = False
    
    ret = xml.Load("http://b.hatena.ne.jp/sample/rss")
    
    If ret Then
        Set nodeList = xml.SelectNodes("/rdf:RDF/rss:item/rss:title")
        
        For i = 0 To nodeList.Length - 1
            ActiveSheet.Cells(i + 1, 1).Value = nodeList.item(i).Text
        Next
    End If
End Sub

2016年8月1日月曜日

POIで絵文字を出力するためのハック

この記事では、POIを使ってExcel(xlsx)ファイルへ絵文字を出力するためのハックを紹介します。
「ハック」と表現したように、あまりお行儀のいい方法ではないと思っているので、もっとスマートな方法を御存知でしたらコメントなどで教えていただけると嬉しいです。

POIで絵文字を出力しようとすると、そのままでは「??」と文字化けしたようになってしまいます。
これは、Apache XMLBeansのTextSaver(org.apache.xmlbeans.impl.Saver.TextSaver)クラスのisBadCharメソッドが絵文字に対してtrueを返すからです。
Apache XMLBeansはすでに開発が終了しています。isBadCharメソッドはprivateで定義されているので、オーバーライドもできません。私はクラスを上書きする方法を選択しました。

まずは、Apache XMLBeansのソースを取得します。
svn export http://svn.apache.org/repos/asf/xmlbeans/trunk/ xmlbeans

次に、xmlbeans\src\store\org\apache\xmlbeans\impl\Saver.javaをプロジェクトへコピーします。必要なディレクトリ(org\apache\xmlbeans\impl)を作成し、その配下へコピーします。

最後に、isBadCharメソッドを書き換えます。書き換え後は次のようになります。
        private boolean isBadChar ( char ch )
        {
            if (Character.isHighSurrogate(ch) ||
                Character.isLowSurrogate(ch))
                return false;
            return ! (
                (ch >= 0x20 && ch <= 0xD7FF ) ||
                (ch >= 0xE000 && ch <= 0xFFFD) ||
                (ch >= 0x10000 && ch <= 0x10FFFF) ||
                (ch == 0x9) || (ch == 0xA) || (ch == 0xD)
                );
        }
OptimizedForSpeedSaverにも同様のメソッドがあるので、ついでに書き換えておきます。

以上で絵文字を出力できるようになります。