OpenOfficeでCSV出力するマクロを作る

イントロダクション

こちらの記事で、DBを作成しようとしていますが、尾¥登録するデータをどうするかで悩んだ結果。

依然作成した「地域情報一覧ページのデータ」を登録しようという結論に至りました。

CSVファイルを作る

地域情報一覧ページを作成しました、このページを作成するのにJSで表示するデータを作りましいた。これは、スプレッドシートになっているのですが、これからCSVファイルを作りたいと思います。

その前に、作成したマクロを実行するボタンの作り方を残しておきます。

ボタンの作成方法

マクロのためにJREを設定する

OpenOffice(Calc)

オープンオフィスを使用して、VBA的なプログラムが使えるのでそれを使用してデータを出力します。まずはOpenOfficeのセットアップです。

Java32bitをインストール

OpenOfficeは、32ビットで動いているようです。なので64ビット版ではなく32ビット版のJREが必要になります。
こちらのリンクから、ダウンロードおよびインストールできます。

インストールしたら、ProgramFiles(x86)野は以下にJavaフォルダができるので、その中のJREを選択します。
メニューの「ツール」→「オプション」→「OpenOffice」→「セキュリティ」を選択します。

マクロの作成

「マクロ」というのは、短髪で動く処理のことを指します。C言語でも「マクロ」がありますが、これもすぐに呼び出すことができる便利なものです。

マクロは、下のように複数の言語を使用できるようです。

マクロ起動用のボタンを作る

上部のメニュー、「表示」→「ツールバー」→「フォームコントロール」でコントロールを開きます。
ボタンを追加して、マクロを登録します。

マクロを作る

とりあえずは、こんなところです。次は、CSVファイルを出力するマクロを作りたいと思います。

ここで、はじめに作成したコードをベースにCSVファイルを出力するコードを作成したいと思います。


Sub Main

MsgBox "Hello"

End Sub

現状では、「Hello」とポップアップで文言を表示するだけのプログラムです。上記の動画で使用しているものです。

OpenOffice Calc1のコード

エクセルVBAのように、コードを書くにはどのように書いたら良いか、まとめます。

まずは、変数定義から必要になります。

Dim oSheet AS Object
Dim oCell AS Object
Dim oCell2 AS Object

今回取得したいのは、シートとセルです。なので、それぞれの変数を用意します。

シートを取得する

ズバリ下のコードです。引数にあるのは、シート名です。

oSheet = ThisComponent.Sheets.getByName("pref_mst")

「pref_mst」シートを取得します。

セルを取得する

同様に、「C2」のセルを取得する。

oCell = oSheet.getCellrangeByName("C2")

このセルに値をセットしたいので、下のように書きます。

oCell.String = "aaA"
oCell2.Value = 12

シート名を取得する

シート名を「oSheet.Name」で取得、「oCell.String = 」で値をセットする。

oCell.String = oSheet.Name

現状のコード

とりあえずは、ここまでコードを書きました。こんな感じでCSVファイルを出力する予定です。

Sub Main

Dim oSheet AS Object
Dim oCell AS Object
Dim oCell2 AS Object

' ****************
' 練習用のコード
' ****************

oSheet = ThisComponent.Sheets.getByName("pref_mst")
'oCell = oSheet.getCellrangeByName("C2")
'oCell.String = "aaA" ' 文字列をセット
'
'oCell2 = oSheet.getCellrangeByName("C3")
'oCell2.String = oSheet.Name

' シート数だけシートを取得する
Dim oEnum As Object
oEnum = oSheet.createEnumeration()

While(oEnum.hasMoreElements())
    '' シート取得
    'セルを取得
End While
End Sub

シートの内容を取得

ここまで来たら、あとはシートの中身を取得してデータ(カンマ区切り)をCSVファイルに出力するだけです。

変更点

いきなりですが、シートを取得するのに「Enumeration」がうまく使えなかったので、FOR文に切り替えて処理を行うことにしました。
ファイル内にある、シートの数を取得するのに下のようなコードを使用しました。

' ファイルの取得
doc = ThisComponent
' シート数の取得
count = doc.getSheets().count
' 全シートの取得
shList = doc.getSheets()

<変更前>

ループをするのにWhile文を使用していました。

While(oEnum.hasMoreElements())
    '' シート取得
    'セルを取得
End While

<変更後>

For i = 0 to count
    ・
    ・
    ・
Next i

コードの実装

ファイル内の全シートを取得までは実装できたので、次は取得したシートからデータの取得を行います。

シートの取得とファイルオープン

下のように書きました。シートの取得はインデックス指定で行います。これはシート数までループする形で実装しました。
そして、出力するファイル名はシート名+".csv"で定義、ファイルを開き、「Print #fileNum, line」で行を追加していきます。「#fileNum」はファイルを開いた時の番号です。これを基準にしてファイルオープンしているオブジェクトを管理するのかな?

    ' シートの取得
    sheet = shList.getByIndex(i)
    ' 出力ファイル名
    fileName = root + sheet.Name + ".csv"
    ' ファイルを開く
    Open fileName For Output As #fileNum

1行のデータを取得する

ズバリ下のようなコードで書きました。

    ' 1行分のデータを取得してファイル出力
    tmp = sheet.getCellByPosition(cellRow, cellColumn).getString

「cellRow」はシートの行番号を示し。「cellColumn」は列番号を示します。
つまりループの1回目はそれぞれの値が(0, 0)の状態から処理を開始します。

繰り返しの条件

1シートにつき、データのある分だけループするので、「セルの中身が空だったら・・・」という条件でループしました。
結局は変数「tmp」をうまく使ってやるところです。ここが一番苦労しました。

While(tmp <> "")

最終的なコード

REM  *****  BASIC  *****

Sub Main

dim doc as object
dim count as Integer
dim shList as object
dim sheet as object

doc = ThisComponent
count = doc.getSheets().count
shList = doc.getSheets()

' シートを順に取得する
dim root as String
root = "C:\Users\tak45\OneDrive\ドキュメント\sampleCode\Gotochi\data\"
dim fileName as String

' セルのポジション
Dim cellRpw as Integer
Dim cellColumn as integer

Dim line as String
Dim tmp as String

cellRow = 0
cellColumn = 0

Dim fileNum as Integer
fileNum = Freefile()

for i = 0 to count
    ' シートの取得
    sheet = shList.getByIndex(i)
    ' 出力ファイル名
    fileName = root + sheet.Name + ".csv"
    ' ファイルを開く
    Open fileName For Output As #fileNum

    tmp = ""
    line = ""

    ' 1行分のデータを取得してファイル出力
    tmp = sheet.getCellByPosition(cellRow, cellColumn).getString
    if tmp <> "" then
        line = tmp + ", "
    else
        exit for
    end if

    cellColumn = cellColumn + 1
    While(tmp <> "")
        tmp = sheet.getCellByPosition(cellColumn, cellRow).getString 
        if tmp <> "" then
            line = line + tmp + ", "
            cellColumn = cellColumn + 1
        else
            Dim resCount as Integer
            resCount = len(line) - 2
            line = Left(line, resCount)
            cellRow = cellRow + 1
            cellColumn = 0
            Print #fileNum, line
            tmp = sheet.getCellByPosition(cellColumn, cellRow).getString 
            line = ""
        end if

    WEnd
    cellRow = 0
    'ファイルを閉じる
    Close #fileNum

    if i = 2 then
        exit for
    end if

next i

End Sub

でわでわ。。。

投稿者:

takunoji

音響、イベント会場設営業界からIT業界へ転身。現在はJava屋としてサラリーマンをやっている。自称ガテン系プログラマー(笑) Javaプログラミングを布教したい、ラスパイとJavaの相性が良いことに気が付く。 Spring framework, Struts, Seaser, Hibernate, Playframework, JavaEE6, JavaEE7などの現場経験あり。 SQL, VBA, PL/SQL, コマンドプロント, Shellなどもやります。