Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def read_style_table(xml_source):
"""Read styles from the shared style table"""
table = {}
xmlns = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
root = fromstring(xml_source)
custom_num_formats = parse_custom_num_formats(root, xmlns)
color_index = parse_color_index(root, xmlns)
font_list = parse_fonts(root, xmlns, color_index)
fill_list = parse_fills(root, xmlns, color_index)
border_list = parse_borders(root, xmlns, color_index)
builtin_formats = NumberFormat._BUILTIN_FORMATS
cell_xfs = root.find(QName(xmlns, 'cellXfs').text)
if cell_xfs is not None: # can happen on bad OOXML writers (e.g. Gnumeric)
cell_xfs_nodes = cell_xfs.findall(QName(xmlns, 'xf').text)
for index, cell_xfs_node in enumerate(cell_xfs_nodes):
new_style = Style(static=True)
number_format_id = int(cell_xfs_node.get('numFmtId'))
if number_format_id < 164:
new_style.number_format.format_code = \
builtin_formats.get(number_format_id, 'General')
else:
if number_format_id in custom_num_formats:
new_style.number_format.format_code = \
custom_num_formats[number_format_id]
else:
raise MissingNumberFormat('%s' % number_format_id)
def parse_borders(root, xmlns, color_index):
"""Read in the boarders"""
border_list = []
borders = root.find(QName(xmlns, 'borders').text)
if borders is not None:
boarderNodes = borders.findall(QName(xmlns, 'border').text)
count = 0
for boarder in boarderNodes:
newBorder = Borders()
if boarder.get('diagonalup') == 1:
newBorder.diagonal_direction = newBorder.DIAGONAL_UP
if boarder.get('diagonalDown') == 1:
if newBorder.diagonal_direction == newBorder.DIAGONAL_UP:
newBorder.diagonal_direction = newBorder.DIAGONAL_BOTH
else:
newBorder.diagonal_direction = newBorder.DIAGONAL_DOWN
for side in ('left', 'right', 'top', 'bottom', 'diagonal'):
node = boarder.find(QName(xmlns, side).text)
if node is not None:
borderSide = getattr(newBorder,side)
if node.get('style') is not None:
def parse_fonts(root, xmlns, color_index):
"""Read in the fonts"""
font_list = []
fonts = root.find(QName(xmlns, 'fonts').text)
if fonts is not None:
font_nodes = fonts.findall(QName(xmlns, 'font').text)
for font_node in font_nodes:
font = Font()
font.size = font_node.find(QName(xmlns, 'sz').text).get('val')
font.name = font_node.find(QName(xmlns, 'name').text).get('val')
font.bold = True if len(font_node.findall(QName(xmlns, 'b').text)) else False
font.italic = True if len(font_node.findall(QName(xmlns, 'i').text)) else False
if len(font_node.findall(QName(xmlns, 'u').text)):
underline = font_node.find(QName(xmlns, 'u').text).get('val')
font.underline = underline if underline else 'single'
color = font_node.find(QName(xmlns, 'color').text)
if color is not None:
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
font.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
if color.get('tint') is not None:
font.color.index = 'theme:%s:%s' % (color.get('theme'), color.get('tint'))
def parse_fonts(root, xmlns, color_index):
"""Read in the fonts"""
font_list = []
fonts = root.find(QName(xmlns, 'fonts').text)
if fonts is not None:
font_nodes = fonts.findall(QName(xmlns, 'font').text)
for font_node in font_nodes:
font = Font()
font.size = font_node.find(QName(xmlns, 'sz').text).get('val')
font.name = font_node.find(QName(xmlns, 'name').text).get('val')
font.bold = True if len(font_node.findall(QName(xmlns, 'b').text)) else False
font.italic = True if len(font_node.findall(QName(xmlns, 'i').text)) else False
if len(font_node.findall(QName(xmlns, 'u').text)):
underline = font_node.find(QName(xmlns, 'u').text).get('val')
font.underline = underline if underline else 'single'
color = font_node.find(QName(xmlns, 'color').text)
if color is not None:
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
font.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
def read_style_table(xml_source):
"""Read styles from the shared style table"""
table = {}
xmlns = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
root = fromstring(xml_source)
custom_num_formats = parse_custom_num_formats(root, xmlns)
color_index = parse_color_index(root, xmlns)
font_list = parse_fonts(root, xmlns, color_index)
fill_list = parse_fills(root, xmlns, color_index)
border_list = parse_borders(root, xmlns, color_index)
builtin_formats = NumberFormat._BUILTIN_FORMATS
cell_xfs = root.find(QName(xmlns, 'cellXfs').text)
if cell_xfs is not None: # can happen on bad OOXML writers (e.g. Gnumeric)
cell_xfs_nodes = cell_xfs.findall(QName(xmlns, 'xf').text)
for index, cell_xfs_node in enumerate(cell_xfs_nodes):
new_style = Style(static=True)
number_format_id = int(cell_xfs_node.get('numFmtId'))
if number_format_id < 164:
new_style.number_format.format_code = \
builtin_formats.get(number_format_id, 'General')
else:
if number_format_id in custom_num_formats:
new_style.number_format.format_code = \
custom_num_formats[number_format_id]
else:
raise MissingNumberFormat('%s' % number_format_id)
if cell_xfs_node.get('applyAlignment') == '1':
alignment = cell_xfs_node.find(QName(xmlns, 'alignment').text)
newBorder = Borders()
if boarder.get('diagonalup') == 1:
newBorder.diagonal_direction = newBorder.DIAGONAL_UP
if boarder.get('diagonalDown') == 1:
if newBorder.diagonal_direction == newBorder.DIAGONAL_UP:
newBorder.diagonal_direction = newBorder.DIAGONAL_BOTH
else:
newBorder.diagonal_direction = newBorder.DIAGONAL_DOWN
for side in ('left', 'right', 'top', 'bottom', 'diagonal'):
node = boarder.find(QName(xmlns, side).text)
if node is not None:
borderSide = getattr(newBorder,side)
if node.get('style') is not None:
borderSide.border_style = node.get('style')
color = node.find(QName(xmlns, 'color').text)
if color is not None:
# Ignore 'auto'
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
borderSide.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
if color.get('tint') is not None:
borderSide.color.index = 'theme:%s:%s' % (color.get('theme'), color.get('tint'))
else:
borderSide.color.index = 'theme:%s:' % color.get('theme') # prefix color with theme
elif color.get('rgb'):
borderSide.color.index = color.get('rgb')
count += 1
border_list.append(newBorder)
return border_list
def parse_fonts(root, xmlns, color_index):
"""Read in the fonts"""
font_list = []
fonts = root.find(QName(xmlns, 'fonts').text)
if fonts is not None:
font_nodes = fonts.findall(QName(xmlns, 'font').text)
for font_node in font_nodes:
font = Font()
font.size = font_node.find(QName(xmlns, 'sz').text).get('val')
font.name = font_node.find(QName(xmlns, 'name').text).get('val')
font.bold = True if len(font_node.findall(QName(xmlns, 'b').text)) else False
font.italic = True if len(font_node.findall(QName(xmlns, 'i').text)) else False
if len(font_node.findall(QName(xmlns, 'u').text)):
underline = font_node.find(QName(xmlns, 'u').text).get('val')
font.underline = underline if underline else 'single'
color = font_node.find(QName(xmlns, 'color').text)
if color is not None:
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
font.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
if color.get('tint') is not None:
font.color.index = 'theme:%s:%s' % (color.get('theme'), color.get('tint'))
else:
font.color.index = 'theme:%s:' % color.get('theme') # prefix color with theme
elif color.get('rgb'):
font.color.index = color.get('rgb')
font_list.append(font)
return font_list
def parse_fills(root, xmlns, color_index):
"""Read in the list of fills"""
fill_list = []
fills = root.find(QName(xmlns, 'fills').text)
count = 0
if fills is not None:
fillNodes = fills.findall(QName(xmlns, 'fill').text)
for fill in fillNodes:
# Rotation is unset
patternFill = fill.find(QName(xmlns, 'patternFill').text)
if patternFill is not None:
newFill = Fill()
newFill.fill_type = patternFill.get('patternType')
fgColor = patternFill.find(QName(xmlns, 'fgColor').text)
if fgColor is not None:
if fgColor.get('indexed') is not None and 0 <= int(fgColor.get('indexed')) < len(color_index):
newFill.start_color.index = color_index[int(fgColor.get('indexed'))]
elif fgColor.get('indexed') is not None:
# Invalid color - out of range of color_index, set to white
newFill.start_color.index = 'FFFFFFFF'
elif fgColor.get('theme') is not None:
if fgColor.get('tint') is not None:
newFill.start_color.index = 'theme:%s:%s' % (fgColor.get('theme'), fgColor.get('tint'))
else:
newFill.start_color.index = 'theme:%s:' % fgColor.get('theme') # prefix color with theme
def parse_fonts(root, xmlns, color_index):
"""Read in the fonts"""
font_list = []
fonts = root.find(QName(xmlns, 'fonts').text)
if fonts is not None:
font_nodes = fonts.findall(QName(xmlns, 'font').text)
for font_node in font_nodes:
font = Font()
font.size = font_node.find(QName(xmlns, 'sz').text).get('val')
font.name = font_node.find(QName(xmlns, 'name').text).get('val')
font.bold = True if len(font_node.findall(QName(xmlns, 'b').text)) else False
font.italic = True if len(font_node.findall(QName(xmlns, 'i').text)) else False
if len(font_node.findall(QName(xmlns, 'u').text)):
underline = font_node.find(QName(xmlns, 'u').text).get('val')
font.underline = underline if underline else 'single'
color = font_node.find(QName(xmlns, 'color').text)
if color is not None:
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
font.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
if color.get('tint') is not None:
font.color.index = 'theme:%s:%s' % (color.get('theme'), color.get('tint'))
else:
font.color.index = 'theme:%s:' % color.get('theme') # prefix color with theme
elif color.get('rgb'):
def parse_fonts(root, xmlns, color_index):
"""Read in the fonts"""
font_list = []
fonts = root.find(QName(xmlns, 'fonts').text)
if fonts is not None:
font_nodes = fonts.findall(QName(xmlns, 'font').text)
for font_node in font_nodes:
font = Font()
font.size = font_node.find(QName(xmlns, 'sz').text).get('val')
font.name = font_node.find(QName(xmlns, 'name').text).get('val')
font.bold = True if len(font_node.findall(QName(xmlns, 'b').text)) else False
font.italic = True if len(font_node.findall(QName(xmlns, 'i').text)) else False
if len(font_node.findall(QName(xmlns, 'u').text)):
underline = font_node.find(QName(xmlns, 'u').text).get('val')
font.underline = underline if underline else 'single'
color = font_node.find(QName(xmlns, 'color').text)
if color is not None:
if color.get('indexed') is not None and 0 <= int(color.get('indexed')) < len(color_index):
font.color.index = color_index[int(color.get('indexed'))]
elif color.get('theme') is not None:
if color.get('tint') is not None:
font.color.index = 'theme:%s:%s' % (color.get('theme'), color.get('tint'))
else:
font.color.index = 'theme:%s:' % color.get('theme') # prefix color with theme
elif color.get('rgb'):
font.color.index = color.get('rgb')
font_list.append(font)
return font_list