SSブログ

続、OpenOffice.org Writer の .odt ファイルを覗いてみる。 [OpenOffice.org]

VBScript で1回書いて。 そのままじゃ表(Calc ではなくて Writer で作成できる表)が存在するとエラーになるという間違いに気づいて訂正してw

んでも、とりあえず書いた表処理コードだと、表を構成するセル個々の内容が「セル1個=テキスト1行」となって出力されるのがなんとなく嫌で。

セル個々に Col, Row でアクセスできれば順にたどって整形して・・・と思ったけど、Col, Row でセルを特定してアクセスする方法が判らなかったので、力技でアクセスしてみたw 表の1行をテキスト1行として出力。 セルの区切りはタブを挟む。 縦3行、横4列の表なら3行のテキストで、1行は4個の内容と3個のタブ・・・という感じで。 セルの中の改行は除去して、なるべく表のレイアウト構造を保つようにして・・ って、なんかイマイチなコードだ・・・もうちょっとシンプルに書きたかったな。

ついでに Calc の表を OLE で貼り付けた場合はどうやってアクセスすればいいのかなと思って調べたけど判らなかったw

Writer のデータをたどる時、LoadComponentFromURL()でファイルを読み込んでから、トップレベル(?)から .Text.createEnumeration でテキストの列挙型データ群を取ってるから、その中には OLE オブジェクトは含まれないだろうし・・・。 たとえば二つのパラグラフの間に挿入された Calc の OLE オブジェクトがあった時、パラグラフ→OLEオブジェクト→パラグラフと順にアクセスするにはどうすればいいんだろう・・と考えて。 んじゃ、OpenOffice.org Writer でテキスト出力してみたらどうなるのかと思って試してみたら、OLEオブジェクトの内容は出てこなかったw

ついでに、Writer 表の中身は1セル=1行として出力されてた。 いや、セル内で改行している場合は、その改行もそのまま出力。 表のレイアウト構造が完全に失われるのは、ちょっとアレだな。

Option Explicit

'引数の受け取り
Dim args
Set args = Wscript.Arguments
If args.Count <> 1 Then
  WScript.Echo "Usage: " & WScript.ScriptName & " odt-file"
  WScript.Quit
End If

'odtファイルのフルパスを得る
Dim oFs
Set oFs = CreateObject("Scripting.FileSystemObject")
Dim sFile
sFile = oFs.GetAbsolutePathName(args.item(0))
Set oFs = Nothing

'OOoの準備
Dim oOOoServiceManager
Set oOOoServiceManager _ 
  = WScript.CreateObject("com.sun.star.ServiceManager")
CheckError

Dim oOOoDesktop
Set oOOoDesktop _ 
  = oOOoServiceManager.createInstance("com.sun.star.frame.Desktop")
CheckError

'OOoデスクトップウィンドウ非表示のためのプロパティ準備
Dim oPropertyValue
Set oPropertyValue _ 
  = oOOoServiceManager.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
oPropertyValue.Name = "Hidden"
oPropertyValue.Value = True

'odtファイルの読み込み
Dim oODT
Set oODT _ 
  = oOOoDesktop.LoadComponentFromURL(_ 
  "file:///" & Replace(sFile, "\", "/"), _ 
  "_blank", 0, Array(oPropertyValue)) 'OOoデスクトップウィンドウ非表示
CheckError
Set oPropertyValue = Nothing

'odtファイルの中のテキストを拾い上げる
Dim oEnum
Set oEnum = oODT.Text.createEnumeration
CheckError
Dim oTextElement
Dim sBody
sBody = ""
While oEnum.hasMoreElements
  Set oTextElement = oEnum.nextElement
  CheckError
  If oTextElement.supportsService("com.sun.star.text.Paragraph") Then
    sBody = sBody & oTextElement.String & VbCrLf
  ElseIf oTextElement.supportsService("com.sun.star.text.TextTable") Then
    sBody = sBody & ConvTableToText(oTextElement) & VbCrLf
  End If
  Set oTextElement = Nothing
Wend

WScript.Echo sBody

Set oTextElement = Nothing
Set oEnum = Nothing

oODT.Dispose
CheckError
Set oODT = Nothing

'OOoデスクトップが他にドキュメントを開いてなければ
Dim oDocs
Set oDocs = oOOoDesktop.getComponents().createEnumeration()
If Not oDocs.hasMoreElements() Then 
  oOOoDesktop.Terminate '閉じる
  CheckError
End If

Set oDocs = Nothing
Set oOOoDesktop = Nothing
Set oOOoServiceManager = Nothing

WScript.Echo "End."
WScript.Quit 

'---------------------------------------------------------------------------
Function CheckError()
  If Err.Number < 1 Then Exit Function
  MsgBox "エラーが発生しました。" & VBCrLf _ 
    & "実行スクリプト: " & WScript.ScriptFullName & VBCrLf _ 
    & "エラー番号: " & CStr(Err.Number) & VBCrLf _ 
    & "エラーメッセージ: " & Err.Description & VBCrLf _ 
    & "日時: " & Now & VBCrLf & VBCrLf , _ 
    vbOKOnly + vbCritical
  WScript.Quit '終了
End Function
'---------------------------------------------------------------------------
Function ConvTableToText(oTbl)
  ConvTableToText = ""
  Dim sCellNames
  sCellNames = oTbl.getCellNames
  Dim oCell
  Dim posRow
  Dim posRowTest
  Dim posNum
  posNum = InNumChrPos(sCellNames(0))
  posRow = CInt(Right(sCellNames(0), Len(sCellNames(0))-(posNum-1)) )
  Dim i
  Dim sep
  sep = ""
  For i = 0 To UBound(sCellNames)
    Set oCell = oTbl.getCellByName(sCellNames(i))
    posNum = InNumChrPos(sCellNames(i))
    posRowTest = CInt(Right(sCellNames(i), Len(sCellNames(i))-(posNum-1)) )
    If (posRow <> posRowTest) Then
      ConvTableToText = ConvTableToText & VbCrLf
      posRow = posRowTest
      sep = ""
    End If
    ConvTableToText = ConvTableToText & sep _ 
      & Replace(oCell.String, VBCrLf, "", 1, -1, vbTextCompare)
    sep = VbTab
  Next
End Function
'---------------------------------------------------------------------------
Function InNumChrPos(sTest)
  InNumChrPos = 0
  If (Len(sTest) = 0) Then Exit Function
  Dim posTest
  Dim posKeep
  posKeep = Len(sTest) + 1
  Dim i
  For i = 0 To 9
    posTest = InStr(1, sTest, CStr(Chr(Asc("0") + i)), vbTextCompare)
    If (posTest > 0) And (posKeep >= posTest) Then posKeep = posTest
  Next
  If (posKeep > Len(sTest)) Then posKeep = 0
  InNumChrPos = posKeep
End Function
'---------------------------------------------------------------------------

WinMerge のプラグインも同様に書き換えればOKか。

んでも、埋め込まれたOLEオブジェクトの内容を扱えないから、差異検出としては弱いなぁ・・・ うーん。


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。