none
MFCでWordファイルの書き出しするとき連続した範囲にルビを設定すると1つ目のルビしか付かない (Range::PhoneticGuide使用) RRS feed

  • 質問

  • VisualStudio2013 MFC  C++でソフトを開発しています。

    ソフトにはWord文書の書き出しがあります。

    範囲を指定したRangeオブジェクトを作成し、Range::PhoneticGuideでルビを設定しています。
    これで殆どが問題無いのですが、
    範囲が連続していると1つ目の範囲のルビしかWordで表示しません。(連続Rangeの間に1文字でも入っていると問題なく表示します)

    連続した範囲でもルビを表示したいので、この問題の回避方法をご教授お願いします。

    以下はサンプルになります。 123と456に別ルビを付けようとしています。

    イタリックやBoldは効いているので、Rangeは問題無さそうです。

    void CTateEditDlg::OnTest()
    {
    Word::_ApplicationPtr  wordApp;
    CComPtr<Word::_Document> wordDoc;
    CComPtr<Documents> docs;

    CoInitialize(NULL);
    wordApp.CreateInstance(L"Word.Application");
    wordApp->get_Documents(&docs);

    TCHAR Buffer[MAX_PATH];
    DWORD dwRet;
    dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
    CString csMessage = Buffer;
    csMessage+=L"\\template.dotx"; // 起動フォルダにテンプレートを置いてます

    COleVariant tmpVariant( csMessage );
    VARIANT variant = tmpVariant.Detach();
    wordDoc = docs->Add(&variant);

    CComPtr<Word::Range> pRange;
    pRange = wordDoc->Range();

    // Wordに文字を設定
    CString strTest = _T("123456");
    pRange->Text = bstr_t( strTest );

    CComVariant from(0);
    CComVariant to(3);
    CComVariant from2(3);
    CComVariant to2(6);
    CComPtr<Word::Range> pRange1 = wordDoc->Range( &from, &to );
    CComPtr<Word::Range> pRange2 = wordDoc->Range( &from2, &to2 );

    // 1つ目
    pRange1->Italic = TRUE;
    pRange1->Bold = TRUE;
    pRange1->PhoneticGuide( _T("ルビ1"), Word::wdPhoneticGuideAlignmentOneTwoOne, 0, 0, _T("") );

    // 2つ目
    pRange2->Italic = TRUE;
    pRange2->Bold = TRUE;
    pRange2->PhoneticGuide( _T("ルビ2"), Word::wdPhoneticGuideAlignmentOneTwoOne, 0, 0, _T("") );

    COleVariant objVariant( _T("c:\\tmp\\test.docx") ); // テスト出力
    variant = objVariant.Detach();
    wordDoc->SaveAs(&variant);
    ::VariantClear( &variant );
    wordDoc->Close();
    CoUninitialize();
    }


    みなさんよろしくお願い致します。



    2018年3月20日 16:29

回答

  • 出来上がったWordドキュメントのフィールドを表示させると判りますが、ルビを振るとフィールドが作られます。
    このときに本来なら後続のRangeのStart,Endはフィールド分加算されて更新されるはずなのですが、直後にあると更新されずにフィールドの中を指してしまうようです。

    ですから、ルビを振る前に取得したRangeを使って次の箇所のルビを振るのではなく、ルビを振った後に次のRangeを取り直さないといけません。
    ですがそれは面倒なので、ルビを振る順番を前から後ろではなく、後ろから前にルビを振っていけば狙った通りになるでしょう。
    (pRange2にルビを振った後にpRange1のルビを振る)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2018年3月21日 0:25

すべての返信

  • 出来上がったWordドキュメントのフィールドを表示させると判りますが、ルビを振るとフィールドが作られます。
    このときに本来なら後続のRangeのStart,Endはフィールド分加算されて更新されるはずなのですが、直後にあると更新されずにフィールドの中を指してしまうようです。

    ですから、ルビを振る前に取得したRangeを使って次の箇所のルビを振るのではなく、ルビを振った後に次のRangeを取り直さないといけません。
    ですがそれは面倒なので、ルビを振る順番を前から後ろではなく、後ろから前にルビを振っていけば狙った通りになるでしょう。
    (pRange2にルビを振った後にpRange1のルビを振る)


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2018年3月21日 0:25
  • 初めRange取得->ルビ振り、Range取得->ルビ振り と連続にやっていたら2個目以降ルビが全く付かなかったので、 はじめに全部のRange取得 -> 後から全部のルビ振りにしていました。

    頂いた情報通り後ろからルビを振るようにしたら上手く行きました。

    大変ありがとうございました。助かりました。

    2018年3月21日 2:35