Word 문서에있는 아래 첨자, 위첨자 및 방정식을 프로그래밍 방식으로 반복하는 방법


12

몇 개의 Word 문서가 있으며 각 문서에는 수백 페이지의 과학 데이터가 포함되어 있습니다.

  • 화학식 (모든 적절한 첨자 및 위첨자가있는 H2SO4)
  • 과학적 숫자 (위첨자를 사용하여 서식이 지정된 지수)
  • 많은 수학 방정식. Word에서 수학 방정식 편집기를 사용하여 작성되었습니다.

문제는이 데이터를 Word에 저장하는 것이 효율적이지 않다는 것입니다. 따라서이 모든 정보를 데이터베이스 (MySQL)에 저장하려고합니다. 서식을 LaTex로 변환하려고합니다.

VBA를 사용하여 Word 문서 내의 모든 하위 암호, 위첨자 및 방정식을 반복 할 수있는 방법이 있습니까?


문서 자체에서 XML 데이터를 추출하는 것에 대해 생각해 보셨습니까? 모든 Microsoft Documents 2007 + (. docx)는 기본적으로 압축 된 xml 파일입니다. xml 파서를 사용하여 검색 할 수 있습니다.
James Mertz

코멘트로 게시하기에는 너무 길어서 답변으로 추가했습니다.
제임스 메르 츠

답변:


12

그렇습니다. Word 파일을 잘 처리하므로 Powershell을 사용하지 않는 것이 좋습니다. 내가 가장 쉬운 방법이라고 생각합니다.

http://www.simple-talk.com/dotnet/.net-tools/com-automation-of-office-applications-via-powershell/의 Powershell 및 Word 자동화에 대한 자세한 내용

좀 더 깊이 파고이 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 파일로 저장합니다. 그래서 나는 첨자 파일이있는 doc 파일을 가지고 있으며 powershell 변환 후 출력은 다음과 같습니다.

<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+ 인 모든 Office 문서에서 직접 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 확장명을 가진 두 개의 이미지가 있습니다. Chrome으로 html 파일을 표시하면 방정식은 괜찮아 보이지만 훌륭하지는 않습니다. 투명한 이미지를 처리 ​​할 수있는 이미지 표시 / 편집 도구로 표시 될 때 모양이 GIF 파일과 일치합니다. Internet Explorer를 사용하여 HTML 파일을 표시하면 수식이 완벽하게 보입니다.

추가 정보

이 정보를 원래 답변에 포함시켜야합니다.

Html로 저장 한 작은 Word 문서를 만들었습니다. 아래 이미지의 3 개 패널에는 원본 Word 문서, Microsoft Internet Explorer에서 표시되는 HTML 문서 및 Chrome에서 표시되는 HTML 문서가 표시됩니다.

IE에 의해 표시되는 원래 단어, HTML 및 Chrome에 의해 표시되는 HTML

앞에서 설명한 것처럼 IE와 Chrome 이미지의 차이점은 방정식이 WMZ 형식으로 한 번, GIF 형식으로 한 번 두 번 저장된 결과입니다. 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로 시작하는 솔루션이 작동하지 않을 것이라고 확신하지만 귀하의 솔루션은 인상적이라고 생각합니다. 스택 오버플로 질문의 결과로 Microsoft의 PublishObjects가 Html을 대부분의 (모든?) 스마트 폰에 사용할 수 없으므로 Excel을 Html로 변환하려고합니다. Word VBA에 대한 경험이 거의 없습니다. Excel과 Outlook VBA에 능숙하며 Acess VBA에 능숙했습니다. 이들은 모두 한 파일의 매크로가 다른 파일에 액세스 할 수 있도록하므로 Word에서도 마찬가지입니다.
Tony Dallimore

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.