Skip to content

Added underline support to Runs #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions docx/enum/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,50 @@ class WD_BREAK_TYPE(object):
TEXT_WRAPPING = 11

WD_BREAK = WD_BREAK_TYPE

class WD_UNDERLINE_TYPE(object):
"""
Underline types, corresponding to WdUnderline enumeration
http://msdn.microsoft.com/en-us/library/office/ff822388(v=office.15).aspx
"""
DASH = 7 # Dashes.
DASH_HEAVY = 23 # Heavy dashes.
DASH_LONG = 39 # Long dashes.
LONG_HEAVY = 55 # Long heavy dashes.
DOT_DASH = 9 # Alternating dots and dashes.
DOT_DASH_HEAVY = 25 # Alternating heavy dots and heavy dashes.
DOT_DOT_DASH = 10 # An alternating dot-dot-dash pattern.
DOT_DOT_DASH_HEAVY = 26 # An alternating heavy dot-dot-dash pattern.
DOTTED = 4 # Dots.
DOTTED_HEAVY = 20 # Heavy dots.
DOUBLE = 3 # A double line.
NONE = 0 # No underline.
SINGLE = 1 # A single line. default.
THICK = 6 # A single thick line.
WAVY = 11 #A single wavy line.
WAVY_DOUBLE = 43 # A double wavy line.
WAVY_HEAVY = 27 # A heavy wavy line.
WORDS = 2 # Underline individual words only.

stringDict={
DASH:'dash',
DASH_HEAVY:'dashHeavy',
DASH_LONG:'dashLong',
LONG_HEAVY:'longHeavy',
DOT_DASH:'dotDash',
DOT_DASH_HEAVY:'dotDashHeavy',
DOT_DOT_DASH:'dotDotDash',
DOT_DOT_DASH_HEAVY:'dotDotDashHeavy',
DOTTED:'dotted',
DOTTED_HEAVY:'dottedHeavy',
DOUBLE:'double',
NONE:'none',
SINGLE:'single',
THICK:'thick',
WAVY:'wavy',
WAVY_DOUBLE:'wavyDouble',
WAVY_HEAVY:'wavyHeavy',
WORDS:'words',
}

WD_UNDERLINE = WD_UNDERLINE_TYPE
8 changes: 6 additions & 2 deletions docx/oxml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# custom element class mappings
# ===========================================================================

from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String
from docx.oxml.shared import CT_DecimalNumber, CT_OnOff, CT_String, CT_Shd

from docx.oxml.shape import (
CT_Blip, CT_BlipFillProperties, CT_GraphicalObject,
Expand Down Expand Up @@ -45,13 +45,16 @@
register_custom_element_class('w:style', CT_Style)
register_custom_element_class('w:styles', CT_Styles)

from docx.oxml.table import CT_Row, CT_Tbl, CT_TblGrid, CT_TblPr, CT_Tc
from docx.oxml.table import CT_Row, CT_Tbl, CT_TblGrid, CT_TblPr, CT_Tc, CT_TcPr
register_custom_element_class('w:tbl', CT_Tbl)
register_custom_element_class('w:tblGrid', CT_TblGrid)
register_custom_element_class('w:tblPr', CT_TblPr)
register_custom_element_class('w:tblStyle', CT_String)
register_custom_element_class('w:tc', CT_Tc)
register_custom_element_class('w:tr', CT_Row)
register_custom_element_class('w:tcPr', CT_TcPr)
register_custom_element_class('w:gridSpan', CT_DecimalNumber)
register_custom_element_class('w:shd', CT_Shd)

from docx.oxml.text import CT_Br, CT_P, CT_PPr, CT_R, CT_RPr, CT_Text
register_custom_element_class('w:b', CT_OnOff)
Expand All @@ -62,6 +65,7 @@
register_custom_element_class('w:dstrike', CT_OnOff)
register_custom_element_class('w:emboss', CT_OnOff)
register_custom_element_class('w:i', CT_OnOff)
register_custom_element_class('w:u', CT_String)
register_custom_element_class('w:iCs', CT_OnOff)
register_custom_element_class('w:imprint', CT_OnOff)
register_custom_element_class('w:noProof', CT_OnOff)
Expand Down
198 changes: 198 additions & 0 deletions docx/oxml/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,201 @@ def val(self):
@val.setter
def val(self, val):
return self.set(qn('w:val'), val)

class CT_Ind(OxmlBaseElement):
@classmethod
def new(cls, nsptagname, valDict):
"""
Return a new ``CT_Ind`` element with tagname *nsptagname* and
attributes set by key, value pairs in *valDict*.
"""
attrsDict = {}
for k, v in valDict.iteritems():
attrsDict[qn('w:'+str(k))] = v
return OxmlElement(nsptagname, attrs=attrsDict)

@property
def valDict(self):
valDict={}
for val in ['start','startChars','end','endChars','left','leftChars',
'right','rightChars','hanging','hangingChars','firstLine',
'firstLineChars']:
valDict[val] = self.get(qn('w:'+val))
return valDict
@valDict.setter
def valDict(self, valDict):
for k, v in valDict:
self.set(qn('w:'+str(k)), v)
return

@property
def start(self):
return self.get(qn('w:start'))
@start.setter
def start(self, start):
return self.set(qn('w:start'), start)

@property
def startChars(self):
return self.get(qn('w:startChars'))
@startChars.setter
def startChars(self, startChars):
return self.set(qn('w:startChars'), startChars)

@property
def end(self):
return self.get(qn('w:end'))
@end.setter
def end(self, end):
return self.set(qn('w:end'), end)

@property
def endChars(self):
return self.get(qn('w:endChars'))
@endChars.setter
def endChars(self, endChars):
return self.set(qn('w:endChars'), endChars)

@property
def left(self):
return self.get(qn('w:left'))
@left.setter
def left(self, left):
return self.set(qn('w:left'), left)

@property
def leftChars(self):
return self.get(qn('w:leftChars'))
@leftChars.setter
def leftChars(self, leftChars):
return self.set(qn('w:leftChars'), leftChars)

@property
def right(self):
return self.get(qn('w:right'))
@right.setter
def right(self, right):
return self.set(qn('w:right'), right)

@property
def rightChars(self):
return self.get(qn('w:rightChars'))
@rightChars.setter
def rightChars(self, rightChars):
return self.set(qn('w:rightChars'), rightChars)

@property
def hanging(self):
return self.get(qn('w:hanging'))
@hanging.setter
def hanging(self, hanging):
return self.set(qn('w:hanging'), hanging)

@property
def hangingChars(self):
return self.get(qn('w:hangingChars'))
@hangingChars.setter
def hangingChars(self, hangingChars):
return self.set(qn('w:hangingChars'), hangingChars)

@property
def firstLine(self):
return self.get(qn('w:firstLine'))
@firstLine.setter
def firstLine(self, firstLine):
return self.set(qn('w:firstLine'), firstLine)

@property
def firstLineChars(self):
return self.get(qn('w:firstLineChars'))
@firstLineChars.setter
def firstLineChars(self, firstLineChars):
return self.set(qn('w:firstLineChars'), firstLineChars)

class CT_Shd(OxmlBaseElement):
@classmethod
def new(cls, nsptagname, valDict):
"""
Return a new ``CT_Shd`` element with tagname *nsptagname* and
attributes set by key, value pairs in *valDict*.
"""
attrsDict = {}
for k, v in valDict.iteritems():
attrsDict[qn('w:'+str(k))] = v
return OxmlElement(nsptagname, attrs=attrsDict)

@property
def valDict(self):
valDict={}
for val in ['val','color', 'themeColor','themeTint', 'themeShade',
'fill', 'themeFill', 'themeFillTint', 'themeFillSHade']:
valDict[val] = self.get(qn('w:'+val))
return valDict
@valDict.setter
def valDict(self, valDict):
for k, v in valDict:
self.set(qn('w:'+str(k)), v)
return

@property
def val(self):
return self.get(qn('w:val'))
@val.setter
def val(self, val):
return self.set(qn('w:val'), val)

@property
def color(self):
return self.get(qn('w:color'))
@color.setter
def color(self, color):
return self.set(qn('w:color'), color)

@property
def themeColor(self):
return self.get(qn('w:themeColor'))
@themeColor.setter
def themeColor(self, themeColor):
return self.set(qn('w:themeColor'), themeColor)

@property
def themeTint(self):
return self.get(qn('w:themeTint'))
@themeTint.setter
def themeTint(self, themeTint):
return self.set(qn('w:themeTint'), themeTint)

@property
def themeShade(self):
return self.get(qn('w:themeShade'))
@themeShade.setter
def themeShade(self, themeShade):
return self.set(qn('w:themeShade'), themeShade)

@property
def fill(self):
return self.get(qn('w:fill'))
@fill.setter
def fill(self, fill):
return self.set(qn('w:fill'), fill)

@property
def themeFill(self):
return self.get(qn('w:themFill'))
@themeFill.setter
def themeFill(self, themeFill):
return self.set(qn('w:themeFill'), themeFill)

@property
def themeFillTint(self):
return self.get(qn('w:themeFillTint'))
@themeFillTint.setter
def themeFillTint(self, themeFillTint):
return self.set(qn('w:themeFillTint'), themeFillTint)

@property
def themeFillShade(self):
return self.get(qn('w:themeFillShade'))
@themeFillShade.setter
def themeFillShade(self, themeFillShade):
return self.set(qn('w:themeFillShade'), themeFillShade)
67 changes: 66 additions & 1 deletion docx/oxml/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from docx.oxml.shared import OxmlBaseElement, OxmlElement, qn

from .exceptions import ValidationError
from .shared import CT_String
from .shared import CT_String, CT_DecimalNumber, CT_Shd
from .text import CT_P


Expand Down Expand Up @@ -251,3 +251,68 @@ def tcPr(self):
<w:tcPr> child element or |None| if not present.
"""
return self.find(qn('w:tcPr'))

def get_or_add_tcPr(self):
"""
Return the tcPr child element, newly added if not present.
"""
tcPr = self.tcPr
if tcPr is None:
tcPr = self._add_tcPr()
return tcPr

def _add_tcPr(self):
"""
Return a newly added tcPr child element. Assumes one is not present.
"""
tcPr = CT_TcPr.new()
self.append(tcPr)
return tcPr

class CT_TcPr(OxmlBaseElement):
"""
``<w:tcPr>`` element, child of ``<w:tc>``, holds child elements that
define cell properties such as gridSpan.
"""
@classmethod
def new(cls):
"""
Return a new ``<w:tcPr>`` element.
"""
return OxmlElement('w:tcPr')

def add_gridSpan(self, span):
"""
Return a new <w:gridSpan> element newly inserted in sequence among
the existing child elements.gridSpan
"""
gridSpan = CT_DecimalNumber.new('w:gridSpan', span)
self.insert(0, gridSpan)
return gridSpan

@property
def gridSpan(self):
"""
Optional <w:gridSpan> child element, or |None| if not present.
"""
return self.find(qn('w:gridSpan'))

def add_shading(self, argDict):
"""
Return a new <w:shd> element newly inserted in sequence among
the existing child elements.gridSpan
"""
shading = CT_Shd.new('w:shd', argDict)
self.insert(0, shading)
return shading

@property
def shading(self):
"""
Optional <w:shd> child element, or |None| if not present.
"""
return self.find(qn('w:shd'))




Loading