2017-08-11 3 views
1

私は何を達成しようとしている:のpython-docxファイルadd_style CTL(複雑テキストレイアウト)言語と

  • はペルシャ語フォントとサイズを定義し、ユーザとのpython-のdocxで段落スタイルを作成します(CTL言語)

問題:

  • 私はこれを行うことができます英語のような非CTL言語:私はペルシャのテキストにテキストを変更した場合

    from docx import Document 
    from docx.enum.style import WD_STYLE_TYPE 
    from docx.shared import Pt 
    
    user_font_name = 'FreeMono' 
    user_font_size = 14 
    
    doc = Document() 
    my_style = doc.styles.add_style('style_name',WD_STYLE_TYPE.PARAGRAPH) 
    my_font = my_style.font 
    my_font.name = user_font_name 
    my_font.size = Pt(user_font_size) 
    p = doc.add_paragraph('some text',my_style) 
    
    # persian_p = doc.add_paragraph('نوشته',my_style) 
    # FreeMono supports Persian language so the problem is not the font 
    
    doc.save('file.docx') 
    
  • はしかし、そのフォントが指定したフォントに変更されません。

    • マイ指定されたフォントが唯一のスタイルの西部フォントファミリを変更し、私はこれを知ってどのようにCTLフォントファミリ

    に何もしない:これはなぜ起こるか

  • docxファイルをLibreOfficeで開き、スタイルを開いてフォントセクションに移動すると、指定したフォントとサイズが「西洋フォントファミリ」にありますが、「CTLフォントファミリ」には表示されません。その結果、CTLのテキストフォントがデフォルトのフォントになります。

追加情報:私は、ユーザーがフォント名を指定したいので、私はこのような状況で私に何か良いをしない既定のスタイルを変更するLinuxの

  • 上のLibreOfficeを使用してい

    1. およびサイズ。
    2. 私のpython-docxファイルのバージョン
    3. (単独のdocx xmlファイルを聞かせて)xmlファイルを変更することで経験がないが、私は私の恐怖に多くを実現のdocxファイルの周り突っつい多くの時間後0.8.6
  • 答えて

    1

    ですその答えは文書のstyle.xmlファイルで嘘でした。文字方向と

    問題:

    • あなたはアラビア語やペルシャ語で入力した場合は、テキストを右に揃えることがわかるかもしれませんここで同様の問題を持つ人々のためにそれを修正する方法のようなものですあなたの問題をすべて解決するわけではありません。テキストの方向を変更しないと、カーソルと句読点は画面の右端に残ります(最後の文字の後には表示されません)。必要に応じて右揃えもありません。これでdocument.xmlの "textDirection"値を 'lrTb'(Left-Right/Top-Bottom)から 'rlTb'に変更してもpython-docxのテキスト方向を変更できないため、LibreOfficeデフォルトの段落スタイル( 'Normal')を私が心に留めていたもの(rtlテキスト方向など)に変更します。これは、実際にはPythonで行う必要がないので、後で多くの時間を節約します。フォント変更、問題の

    のXml説明:

    • は、変更されたデフォルトのスタイルを持つ文書は、そのstyle.xmlファイルに異なる物事のカップルを示しています。 "w:rPr"の下にある標準段落スタイルでは、複雑なスクリプトフォントのサイズ(style.font.sizeを変更することで変更できない)を決定する追加の "w:szCs" w:rFonts "" cs "の値が指定されたペルシャ語フォントになりました。また、 "w:lang"という値 "bidi"は、 "fa-IR"(ペルシア語用)です。ここで私が話しているXML部分です:

      <w:rPr> 
      <w:rFonts w:ascii="FreeMono" w:hAnsi="FreeMono" w:cs="FreeFarsi"/> 
      <w:sz w:val="40"/> 
      <w:rtl/> 
      <w:cs/> 
      <w:szCs w:val="40"/> 
      <w:lang w:val="en-Us" w:bidi="fa-IR"/> 
      </w:rPr> 
      
    • 今style.font.sizeを変更するだけで、「SZ」の値(西部のフォントサイズ)を変更し、「szCs」値(Csに何もしません。フォントサイズ)。同様にstyle.font.nameは "w:rFonts"の "ascii"と "hAnsi"値だけを変更し、 "cs"値には何もしません。したがって、これらの値を変更するには、私のスタイル要素をPythonで変更する必要がありました。

    ソリューション:

    from docx import Document 
    from docx.shared import Pt 
    
    #path to doc with altered style: 
    base_doc_location = 'base.docx' 
    doc = Document(base_doc_location) 
    my_style = doc.styles['Normal'] 
    
    # define your desired fonts 
    user_cs_font_size = 16 
    user_cs_font_name = 'FreeFarsi' 
    user_en_font_size = 12 
    user_en_font_name = 'FreeMono' 
    
    # get <w:rPr> element of this style 
    rpr = my_style.element.rPr 
    
    #================================================== 
    '''This probably isn't necessary if you already 
    have a document with altered style, but just to be 
    safe I'm going to add this here''' 
    
    if rpr.rFonts is None: 
        rpr._add_rFonts() 
    if rpr.sz is None: 
        rpr._add_sz() 
    #================================================== 
    
    '''Get the nsmap string for rpr. This is that "w:" 
    at the start of elements and element values in xml. 
    Like these: 
        <w:rPr> 
        <w:rFonts> 
        w:val 
    
    The nsmap is like a url: 
    http://schemas.openxmlformats.org/... 
    
    Now w:rPr translates to: 
    {nsmap url string}rPr 
    
    So I made the w_nsmap string like this:''' 
    
    w_nsmap = '{'+rpr.nsmap['w']+'}' 
    #================================================== 
    
    '''Because I didn't find any better ways to get an 
    element based on its tag here's a not so great way 
    of getting it: 
    ''' 
    szCs = None 
    lang = None 
    
    for element in rpr: 
        if element.tag == w_nsmap + 'szCs': 
         szCs = element 
        elif element.tag == w_nsmap + 'lang': 
         lang = element 
    
    '''if there is a szCs and lang element in your style 
    those variables will be assigned to it, and if not 
    we make those elements and add them to rpr''' 
    
    if szCs is None: 
        szCs = rpr.makeelement(w_nsmap+'szCs',nsmap=rpr.nsmap) 
    if lang is None: 
        lang = rpr.makeelement(w_nsmap+'lang',nsmap =rpr.nsmap) 
    
    rpr.append(szCs) 
    rpr.append(lang) 
    #================================================== 
    
    '''Now to set our desired values to these elements 
    we have to get attrib dictionary of these elements 
    and set the name of value as key and our value as 
    value for that dict''' 
    
    szCs_attrib = szCs.attrib 
    lang_attrib = lang.attrib 
    rFonts_atr = rpr.rFonts.attrib 
    
    '''sz and szCs values are string values and 2 times 
    the font size so if you want font size to be 11 you 
    have to set sz (for western fonts) or szCs (for CTL 
    fonts) to "22" ''' 
    szCs_attrib[w_nsmap+'val'] =str(int(user_cs_font_size*2)) 
    
    '''Now to change cs font and bidi lang values''' 
    rFonts_atr[w_nsmap+'cs'] = user_cs_font_name 
    lang_attrib[w_nsmap+'bidi'] = 'fa-IR' # For Persian 
    #================================================== 
    
    '''Because we changed default style we don't even 
    need to set style every time we add a new paragraph 
    And if you change font name or size the normal way 
    it won't change these cs values so you can have a 
    font for CTL language and a different font for 
    western language 
    ''' 
    persian_p = doc.add_paragraph('نوشته') 
    en_font = my_style.font 
    en_font.name = user_en_font_name 
    en_font.size = Pt(user_en_font_size) 
    english_p = doc.add_paragraph('some text') 
    
    doc.save('ex.docx') 
    

    編集(コードの改善):
    私はいくつかの改善を使用し、それらの下に、より良いラインを入れることができます行をコメントしました。

    #rpr = my_style.element.rPr # If None it'll throw errors later 
    rpr = my_style.element.get_or_add_rPr() # this avoids potential errors 
    #if rpr.rFonts is None: 
    # rpr._add_rFonts() 
    rFonts = rpr.get_or_add_rFonts() 
    #if rpr.sz is None: 
    # rpr._add_sz() 
    rpr.get_or_add_sz() 
    
    #by importing these you can make elements and set values quicker 
    from docx.oxml.shared import OxmlElement, qn 
    #szCs = rpr.makeelement(w_nsmap+'szCs',nsmap=rpr.nsmap) 
    szCs = OxmlElement('w:szCs') 
    #lang = rpr.makeelement(w_nsmap+'lang',nsmap =rpr.nsmap) 
    lang = OxmlElement('w:lang') 
    
    #szCs_attrib = szCs.attrib 
    #lang_attrib = lang.attrib 
    #rFonts_atr = rpr.rFonts.attrib 
    #szCs_attrib[w_nsmap+'val'] =str(int(user_cs_font_size*2)) 
    #rFonts_atr[w_nsmap+'cs'] = user_cs_font_name 
    #lang_attrib[w_nsmap+'bidi'] = 'fa-IR' 
    
    szCs.set(qn('w:val'),str(int(user_cs_font_size*2))) 
    lang.set(qn('w:bidi'),'fa-IR') 
    rFonts.set(qn('w:cs'),user_cs_font_name) 
    
    関連する問題