Word文書で見つかった下付き文字、上付き文字、方程式をプログラムで繰り返す方法


12

私はいくつかのWord文書を持っています。各文書には数百ページの科学データが含まれています。

  • 化学式(すべての適切な下付き文字と上付き文字を含むH2SO4)
  • 科学的数値(上付き文字を使用して書式設定された指数)
  • 多くの数学方程式。Wordの数式エディターを使用して書かれています。

問題は、このデータをWordに保存するのは効率的ではないということです。そのため、これらすべての情報をデータベース(MySQL)に保存します。書式設定をLaTexに変換します。

VBAを使用してWord文書内のすべてのサブスクリプト、上付き文字、および方程式を反復処理する方法はありますか?


文書内からxmlデータを抽出することを考えましたか?すべてのMicrosoft Documents 2007+(.docx)は、基本的に圧縮されたxmlファイルです。XMLパーサーを使用してこれらを取得できます。
ジェームズメルツ

コメントとして投稿するには長すぎたので、回答として追加しました。
ジェームズメルツ

回答:


12

はいあります。PowershellはWordファイルを非常によく処理するため、Powershellを使用することをお勧めします。私が一番簡単な方法だと思います。

PowershellとWordの自動化の詳細はこちら:http : //www.simple-talk.com/dotnet/.net-tools/com-automation-of-office-applications-via-powershell/

私はもう少し深く掘り下げましたが、このPowerShellスクリプトが見つかりました。

param([string]$docpath,[string]$htmlpath = $docpath)

$srcfiles = Get-ChildItem $docPath -filter "*.doc"
$saveFormat = [Enum]::Parse([Microsoft.Office.Interop.Word.WdSaveFormat], "wdFormatFilteredHTML");
$word = new-object -comobject word.application
$word.Visible = $False

function saveas-filteredhtml
    {
        $opendoc = $word.documents.open($doc.FullName);
        $opendoc.saveas([ref]"$htmlpath\$doc.fullname.html", [ref]$saveFormat);
        $opendoc.close();
    }

ForEach ($doc in $srcfiles)
    {
        Write-Host "Processing :" $doc.FullName
        saveas-filteredhtml
        $doc = $null
    }

$word.quit();

.ps1として保存し、次のコマンドで開始します。

convertdoc-tohtml.ps1 -docpath "C:\Documents" -htmlpath "C:\Output"

指定したディレクトリのすべての.docファイルをhtmlファイルとして保存します。だから私はH2SO4が添え字付きであり、powershell変換後の出力が次のようなdocファイルを持っています:

<html>

<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
<meta name=Generator content="Microsoft Word 14 (filtered)">
<style>
<!--
 /* Font Definitions */
 @font-face
    {font-family:Calibri;
    panose-1:2 15 5 2 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
    {margin-top:0in;
    margin-right:0in;
    margin-bottom:10.0pt;
    margin-left:0in;
    line-height:115%;
    font-size:11.0pt;
    font-family:"Calibri","sans-serif";}
.MsoChpDefault
    {font-family:"Calibri","sans-serif";}
.MsoPapDefault
    {margin-bottom:10.0pt;
    line-height:115%;}
@page WordSection1
    {size:8.5in 11.0in;
    margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
    {page:WordSection1;}
-->
</style>

</head>

<body lang=EN-US>

<div class=WordSection1>

<p class=MsoNormal><span lang=PL>H<sub>2</sub>SO<sub>4</sub></span></p>

</div>

</body>

</html>

添え字にはHTMLに独自のタグがあるので、bashまたはc ++でファイルを解析してbodyから/ bodyにカットし、後でLATEXに変更して残りのHTMLタグを削除するだけです。

http://blogs.technet.com/b/bshukla/archive/2011/09/27/3347395.aspxのコード


それで、HTML添え字を探してそれをLATEX添え字に置き換えるC ++のパーサーを開発しました。

コード:

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>

using namespace std;

 vector < vector <string> > parse( vector < vector <string> > vec, string filename )
{
        /*
                PARSES SPECIFIED FILE. EACH WORD SEPARATED AND
                PLACED IN VECTOR FIELD.

                REQUIRED INCLUDES:
                                #include <iostream>
                                #include <fstream>
                                #include <string>
                                #include <sstream>
                                #include <vector>

            EXPECTS: TWO DIMENTIONAL VECTOR
                     STRING WITH FILENAME
            RETURNS: TWO DIMENTIONAL VECTOR
                     vec[lines][words]
        */
        string vword;
        ifstream vfile;
        string tmp;

         // FILENAME CONVERSION FROM STING
        //  TO CHAR TABLE

        char cfilename[filename.length()+1];
        if( filename.length() < 126 )
        {
                for(int i = 0; i < filename.length(); i++)
                                cfilename[i] = filename[i];
                cfilename[filename.length()] = '\0';
        }
        else return vec;

         // OPENING FILE
        //
        vfile.open( cfilename );
        if (vfile.is_open())
        {
                while ( vfile.good() )
                {
                        getline( vfile, vword );
                        vector < string > vline;
                        vline.clear();

                        for (int i = 0; i < vword.length(); i++)
                        {
                                tmp = "";
                                 // PARSING CONTENT. OMITTING SPACES AND TABS
                                //
                                while (vword[i] != ' ' && vword[i] != ((char)9) && i < vword.length() )
                                        tmp += vword[i++];
                                if( tmp.length() > 0 ) vline.push_back(tmp);
                        }
                        if (!vline.empty())
                                vec.push_back(vline);
                }
                vfile.close();
        }
        else cout << "Unable to open file " << filename << ".\n";
        return vec;
}

int main()
{
        vector < vector < string > > vec;
        vec = parse( vec, "parse.html" );

        bool body = false;
        for (int i = 0; i < vec.size(); i++)
        {
                for (int j = 0; j < vec[i].size(); j++)
                {
                        if ( vec[i][j] == "<body") body=true;
                        if ( vec[i][j] == "</body>" ) body=false;
                        if ( body == true )
                        {
                                for ( int k=0; k < vec[i][j].size(); k++ )
                                {
                                        if (k+4 < vec[i][j].size() )
                                        {
                                                if (    vec[i][j][k]   == '<' &&
                                                        vec[i][j][k+1] == 's' &&
                                                        vec[i][j][k+2] == 'u' &&
                                                        vec[i][j][k+3] == 'b' &&
                                                        vec[i][j][k+4] == '>' )
                                                {

                                                        string tmp = "";
                                                        while (vec[i][j][k+5] != '<')
                                                        {
                                                                tmp+=vec[i][j][k+5];
                                                                k++;
                                                        }
                                                        tmp = "_{" + tmp + "}";
                                                        k=k+5+5;
                                                        cout << tmp << endl;;
                                                }
                                                else cout << vec[i][j][k];
                                        }
                                        else cout << vec[i][j][k];
                                }
                                cout << endl;
                        }
                }
        }
        return 0;
}

htmlファイルの場合:

<html>

<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
<meta name=Generator content="Microsoft Word 14 (filtered)">
<style>
<!--
 /* Font Definitions */
 @font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
 /* Style Definitions */
 p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin-top:0in;
        margin-right:0in;
        margin-bottom:10.0pt;
        margin-left:0in;
        line-height:115%;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
.MsoChpDefault
        {font-family:"Calibri","sans-serif";}
.MsoPapDefault
        {margin-bottom:10.0pt;
        line-height:115%;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
-->
</style>

</head>

<body lang=EN-US>

<div class=WordSection1>

<p class=MsoNormal><span lang=PL>H<sub>2</sub>SO<sub>4</sub></span></p>

</div>

</body>

</html>

出力は次のとおりです。

<body
lang=EN-US>
<div
class=WordSection1>
<p
class=MsoNormal><span
lang=PL>H_{2}
SO_{4}
</span></p>
</div>

もちろん理想的ではありませんが、治療は概念の証明としてです。


3

2007+である任意のオフィスドキュメントからXMLを直接抽出できます。これは、次の方法で行われます。

  1. ファイルの名前を.docxから.zipに変更します
  2. 7zip(またはその他の抽出プログラム)を使用してファイルを抽出します
  3. ドキュメントの実際のコンテンツについては、wordサブフォルダーとdocument.xmlファイルの下の抽出されたフォルダーを確認してください。これには、ドキュメントのすべてのコンテンツが含まれている必要があります。

ここに画像の説明を入力してください

サンプルドキュメントを作成し、bodyタグでこれを見つけました(これはすぐにまとめたので、書式設定が少しずれていることに注意してください)。

<?xml version="1.0" encoding="UTF-8" standalone="true"?>
<w:body>
    -<w:p w:rsidRDefault="000E0C3A" w:rsidR="008B5DAA">
        -<w:r>
            <w:t xml:space="preserve">This </w:t>
        </w:r>
-       <w:r w:rsidRPr="000E0C3A">
            -<w:rPr>
                <w:vertAlign w:val="superscript"/>
            </w:rPr>
            <w:t>is</w:t>
        </w:r>
-       <w:r>
            <w:t xml:space="preserve"> a </w:t>
        </w:r>
            -<w:r w:rsidRPr="000E0C3A">
                -<w:rPr>
                    <w:vertAlign w:val="subscript"/>
                </w:rPr>
                <w:t>test</w:t>
            </w:r>
        -<w:r>
            <w:t>.</w:t>
        </w:r>
    </w:p>
</w:body>

と思われる<w:t>タグがテキストのある<w:rPr>フォントの定義で、<w:p>新しい段落です。

同等の単語は次のようになります。

ここに画像の説明を入力してください


2

私はmnmncが追求したアプローチとは異なるアプローチを見てきました。

テスト用のWord文書をHTMLとして保存しようとしても、成功しませんでした。過去に、Officeで生成されたHTMLには非常に多くのチャフがあり、必要なビットを選択することはほぼ不可能であることがわかりました。私はそれがここにあることがわかった。方程式にも問題がありました。Wordは方程式を画像として保存します。方程式ごとに、WMZの拡張子を持つ画像とGIFの拡張子を持つ画像が2つずつあります。Google Chromeでhtmlファイルを表示する場合、式は問題なく見えますが、見栄えはよくありません。透明な画像を処理できる画像表示/編集ツールで表示すると、外観はGIFファイルと一致します。Internet ExplorerでHTMLファイルを表示すると、方程式は完璧に見えます。

追加情報

この情報を元の回答に含める必要がありました。

Htmlとして保存した小さなWord文書を作成しました。下の画像の3つのパネルは、元のWordドキュメント、Microsoft Internet Explorerで表示されるHTMLドキュメント、およびGoogle Chromeで表示されるHTMLドキュメントを示しています。

IEで表示される元の単語、HtmlおよびChromeで表示されるHTML

前に説明したように、IEとChromeの画像の違いは、WMZ形式とGIF形式の2回保存された式の結果です。Htmlは大きすぎてここに表示できません。

マクロによって作成されるHTMLは次のとおりです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" 
                   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body>
<p>Some ordinary text.</p>
<p>H<sub>2</sub>SO<sub>4</sub>.</p>
<p>Abc &amp; def &gt; ghi &lt; jkl</p>
<p>x<sup>3</sup>+ x<sup>2</sup>+3x+4=0.</p><p></p>
<p><i>Equation</i>  </p>
<p>Mno</p>
<p><i>Equation</i></p>
</body></html>

次のように表示されます:

IEによって表示されるマクロによって作成されたHTML

無料のMathTypeソフトウェア開発キットには明らかにLaTexに変換するルーチンが含まれているため、方程式を変換しようとしませんでした

コードは基本的なものなので、コメントはあまり多くありません。不明な点があるかどうか尋ねます。注:これは元のコードの改良版です。

Sub ConvertToHtml()

  Dim FileNum As Long
  Dim NumPendingCR As Long
  Dim objChr As Object
  Dim PathCrnt As String
  Dim rng As Word.Range
  Dim WithinPara As Boolean
  Dim WithinSuper As Boolean
  Dim WithinSub As Boolean

  FileNum = FreeFile
  PathCrnt = ActiveDocument.Path
  Open PathCrnt & "\TestWord.html" For Output Access Write Lock Write As #FileNum

  Print #FileNum, "<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Frameset//EN""" & _
                  " ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"">" & _
                  vbCr & vbLf & "<html xmlns=""http://www.w3.org/1999/xhtml"" " & _
                  "xml:lang=""en"" lang=""en"">" & vbCr & vbLf & _
                  "<head><meta http-equiv=""Content-Type"" content=""text/html; " _
                  & "charset=utf-8"" />" & vbCr & vbLf & "</head><body>"

  For Each rng In ActiveDocument.StoryRanges

    NumPendingCR = 0
    WithinPara = False
    WithinSub = False
    WithinSuper = False

    Do While Not (rng Is Nothing)
      For Each objChr In rng.Characters
        If objChr.Font.Superscript Then
          If Not WithinSuper Then
            ' Start of superscript
            Print #FileNum, "<sup>";
            WithinSuper = True
          End If
        ElseIf WithinSuper Then
          ' End of superscript
          Print #FileNum, "</sup>";
          WithinSuper = False
        End If
        If objChr.Font.Subscript Then
          If Not WithinSub Then
            ' Start of subscript
            Print #FileNum, "<sub>";
            WithinSub = True
          End If
        ElseIf WithinSub Then
          ' End of subscript
          Print #FileNum, "</sub>";
          WithinSub = False
          End If
          Select Case objChr
            Case vbCr
              NumPendingCR = NumPendingCR + 1
            Case "&"
              Print #FileNum, CheckPara(NumPendingCR, WithinPara) & "&amp;";
            Case "<"
              Print #FileNum, CheckPara(NumPendingCR, WithinPara) & "&lt;";
            Case ">"
              Print #FileNum, CheckPara(NumPendingCR, WithinPara) & "&gt;";
            Case Chr(1)
              Print #FileNum, CheckPara(NumPendingCR, WithinPara) & "<i>Equation</i>";
            Case Else
              Print #FileNum, CheckPara(NumPendingCR, WithinPara) & objChr;
          End Select
      Next
      Set rng = rng.NextStoryRange
    Loop
  Next

  If WithinPara Then
    Print #FileNum, "</p>";
    withpara = False
  End If

  Print #FileNum, vbCr & vbLf & "</body></html>"

  Close FileNum

End Sub
Function CheckPara(ByRef NumPendingCR As Long, _
                   ByRef WithinPara As Boolean) As String

  ' Have a character to output.  Check paragraph status, return
  ' necessary commands and adjust NumPendingCR and WithinPara.

  Dim RtnValue As String

  RtnValue = ""

  If NumPendingCR = 0 Then
    If Not WithinPara Then
      CheckPara = "<p>"
      WithinPara = True
    Else
      CheckPara = ""
    End If
    Exit Function
  End If

  If WithinPara And (NumPendingCR > 0) Then
    ' Terminate paragraph
    RtnValue = "</p>"
    NumPendingCR = NumPendingCR - 1
    WithinPara = False
  End If
  Do While NumPendingCR > 1
    ' Replace each pair of CRs with an empty paragraph
    RtnValue = RtnValue & "<p></p>"
    NumPendingCR = NumPendingCR - 2
  Loop
  RtnValue = RtnValue & vbCr & vbLf & "<p>"
  WithinPara = True
  NumPendingCR = 0

  CheckPara = RtnValue

End Function

すごい仕事。複数のファイルで機能しますか、または変換したいファイル内に配置する必要がありますか?
mnmnc

@mnmnc。ありがとうございました。あなたのソリューションは印象的だと思いますが、Microsoft Htmlで始まるソリューションが機能するとは思わないでしょう。Stack Overflowの質問の結果、MicrosoftのPublishObjectsはほとんどの(すべての?)スマートフォンに受け入れられないHtmlを作成するため、ExcelをHtmlに変換する作業を行っています。Word VBAの経験はほとんどありません。私はExcelとOutlook VBAで最高であり、かつてはAcess VBAが得意でした。これらはすべて、1つのファイル内のマクロが他のファイルにアクセスすることを許可するため、Wordについても同じことが当てはまります。
トニーダリモア

0

これを行う最も簡単な方法は、VBAの次の行だけです。

Sub testing()
With ActiveDocument.Content.Find
 .ClearFormatting
 .Format = True
 .Font.Superscript = True
 .Execute Forward:=True
End With

End Sub

これにより、すべての上付きテキストが検索されます。それで何かをしたい場合は、メソッドに挿入するだけです。たとえば、上付き文字で「super」という単語を見つけて「super found」に変換するには、次のようにします。

Sub testing()

With ActiveDocument.Content.Find
 .ClearFormatting
 .Format = True
 .Font.Superscript = True
 .Execute Forward:=True, Replace:=wdReplaceAll, _
 FindText:="super", ReplaceWith:="super found"
End With

End Sub
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.