Convert openpyxl to relative imports

This commit is contained in:
Kenneth Reitz
2011-05-12 17:54:00 -04:00
parent 322283b8f9
commit 6b6ef70c61
26 changed files with 337 additions and 338 deletions
+8 -8
View File
@@ -26,14 +26,14 @@
"""Imports for the openpyxl package."""
# package imports
from openpyxl import cell
from openpyxl import namedrange
from openpyxl import style
from openpyxl import workbook
from openpyxl import worksheet
from openpyxl import reader
from openpyxl import shared
from openpyxl import writer
from . import cell
from . import namedrange
from . import style
from . import workbook
from . import worksheet
from . import reader
from . import shared
from . import writer
# constants
+8 -8
View File
@@ -38,10 +38,10 @@ import datetime
import re
# package imports
from openpyxl.shared.date_time import SharedDate
from openpyxl.shared.exc import CellCoordinatesException, \
from .shared.date_time import SharedDate
from .shared.exc import CellCoordinatesException, \
ColumnStringIndexException, DataTypeException
from openpyxl.style import NumberFormat
from .style import NumberFormat
# constants
COORD_RE = re.compile('^[$]?([A-Z]+)[$]?(\d+)$')
@@ -70,12 +70,12 @@ def absolute_coordinate(coord_string):
def column_index_from_string(column, fast = False):
"""Convert a column letter into a column number (e.g. B -> 2)
Excel only supports 1-3 letter column names from A -> ZZZ, so we
restrict our column names to 1-3 characters, each in the range A-Z.
.. note::
Fast mode is faster but does not check that all letters are capitals between A and Z
"""
@@ -349,7 +349,7 @@ class Cell(object):
:rtype: string
"""
return '%s%s' % (self.column, self.row)
@property
def address(self):
"""Return the coordinate string for this cell (e.g. 'B12')
@@ -376,7 +376,7 @@ class Cell(object):
def is_date(self):
"""Returns whether the value is *probably* a date or not
:rtype: bool
"""
return (self.has_style
+66 -66
View File
@@ -25,20 +25,20 @@ THE SOFTWARE.
import math
from openpyxl.style import NumberFormat
from openpyxl.drawing import Drawing, Shape
from openpyxl.shared.units import pixels_to_EMU, short_color
from openpyxl.cell import get_column_letter
from .style import NumberFormat
from .drawing import Drawing, Shape
from .shared.units import pixels_to_EMU, short_color
from .cell import get_column_letter
class Axis(object):
POSITION_BOTTOM = 'b'
POSITION_LEFT = 'l'
ORIENTATION_MIN_MAX = "minMax"
def __init__(self):
self.orientation = self.ORIENTATION_MIN_MAX
self.number_format = NumberFormat()
for attr in ('position','tick_label_position','crosses',
@@ -47,11 +47,11 @@ class Axis(object):
self.min = 0
self.max = None
self.unit = None
@classmethod
def default_category(cls):
""" default values for category axes """
ax = Axis()
ax.id = 60871424
ax.cross = 60873344
@@ -62,11 +62,11 @@ class Axis(object):
ax.label_align = 'ctr'
ax.label_offset = 100
return ax
@classmethod
def default_value(cls):
""" default values for value axes """
ax = Axis()
ax.id = 60873344
ax.cross = 60871424
@@ -82,7 +82,7 @@ class Reference(object):
""" a simple wrapper around a serie of reference data """
def __init__(self, sheet, pos1, pos2=None):
self.sheet = sheet
self.pos1 = pos1
self.pos2 = pos2
@@ -93,10 +93,10 @@ class Reference(object):
return 'str'
else:
return 'num'
def _get_ref(self):
""" format excel reference notation """
if self.pos2:
return '%s!$%s$%s:$%s$%s' % (self.sheet.title,
get_column_letter(self.pos1[1]+1), self.pos1[0]+1,
@@ -104,11 +104,11 @@ class Reference(object):
else:
return '%s!$%s$%s' % (self.sheet.title,
get_column_letter(self.pos1[1]+1), self.pos1[0]+1)
def _get_cache(self):
""" read data in sheet - to be used at writing time """
cache = []
if self.pos2:
for row in range(self.pos1[0], self.pos2[0]+1):
@@ -118,15 +118,15 @@ class Reference(object):
cell = self.sheet.cell(row=self.pos1[0], column=self.pos1[1])
cache.append(cell.value)
return cache
class Serie(object):
""" a serie of data and possibly associated labels """
MARKER_NONE = 'none'
def __init__(self, values, labels=None, legend=None, color=None, xvalues=None):
self.marker = Serie.MARKER_NONE
self.values = values
self.xvalues = xvalues
@@ -134,13 +134,13 @@ class Serie(object):
self.legend = legend
self.error_bar = None
self._color = color
def _get_color(self):
return self._color
def _set_color(self, color):
self._color = short_color(color)
color = property(_get_color, _set_color)
def get_min_max(self):
@@ -152,43 +152,43 @@ class Serie(object):
else:
vals = self.values._get_cache()
return min(vals), max(vals)
def __len__(self):
return len(self.values.cache)
class Legend(object):
def __init__(self):
self.position = 'r'
self.layout = None
class ErrorBar(object):
PLUS = 1
MINUS = 2
PLUS_MINUS = 3
def __init__(self, _type, values):
self.type = _type
self.values = values
class Chart(object):
""" raw chart class """
GROUPING_CLUSTERED = 'clustered'
GROUPING_STANDARD = 'standard'
BAR_CHART = 1
LINE_CHART = 2
SCATTER_CHART = 3
def __init__(self, _type, grouping):
self._series = []
# public api
self.type = _type
self.grouping = grouping
@@ -198,46 +198,46 @@ class Chart(object):
self.lang = 'fr-FR'
self.title = ''
self.print_margins = dict(b=.75, l=.7, r=.7, t=.75, header=0.3, footer=.3)
# the containing drawing
self.drawing = Drawing()
# the offset for the plot part in percentage of the drawing size
self.width = .6
self.height = .6
self.margin_top = self._get_max_margin_top()
self.margin_left = 0
# the user defined shapes
self._shapes = []
def add_serie(self, serie):
serie.id = len(self._series)
self._series.append(serie)
self._compute_min_max()
if not None in [s.xvalues for s in self._series]:
self._compute_xmin_xmax()
def add_shape(self, shape):
shape._chart = self
self._shapes.append(shape)
def get_x_units(self):
""" calculate one unit for x axis in EMU """
return max([len(s.values._get_cache()) for s in self._series])
def get_y_units(self):
""" calculate one unit for y axis in EMU """
dh = pixels_to_EMU(self.drawing.height)
return (dh * self.height) / self.y_axis.max
def get_y_chars(self):
""" estimate nb of chars for y axis """
_max = max([max(s.values._get_cache()) for s in self._series])
return len(str(int(_max)))
@@ -265,14 +265,14 @@ class Chart(object):
if mul is not None:
maxi = maxi/mul
unit = unit/mul
if maxi / unit > 9:
# no more that 10 ticks
unit *= 2
self.y_axis.max = maxi
self.y_axis.unit = unit
def _compute_xmin_xmax(self):
""" compute x axis limits and units """
@@ -297,44 +297,44 @@ class Chart(object):
if mul is not None:
maxi = maxi/mul
unit = unit/mul
if maxi / unit > 9:
# no more that 10 ticks
unit *= 2
self.x_axis.max = maxi
self.x_axis.unit = unit
def _get_max_margin_top(self):
mb = Shape.FONT_HEIGHT + Shape.MARGIN_BOTTOM
plot_height = self.drawing.height * self.height
return float(self.drawing.height - plot_height - mb)/self.drawing.height
def _get_min_margin_left(self):
ml = (self.get_y_chars() * Shape.FONT_WIDTH) + Shape.MARGIN_LEFT
return float(ml)/self.drawing.width
def _get_margin_top(self):
""" get margin in percent """
return min(self.margin_top, self._get_max_margin_top())
def _get_margin_left(self):
return max(self._get_min_margin_left(), self.margin_left)
class BarChart(Chart):
def __init__(self):
super(BarChart, self).__init__(Chart.BAR_CHART, Chart.GROUPING_CLUSTERED)
class LineChart(Chart):
def __init__(self):
super(LineChart, self).__init__(Chart.LINE_CHART, Chart.GROUPING_STANDARD)
class ScatterChart(Chart):
def __init__(self):
super(ScatterChart, self).__init__(Chart.SCATTER_CHART, Chart.GROUPING_STANDARD)
+50 -51
View File
@@ -24,11 +24,11 @@ THE SOFTWARE.
'''
import math
from openpyxl.style import Color
from openpyxl.shared.units import pixels_to_EMU, EMU_to_pixels, short_color
from .style import Color
from .shared.units import pixels_to_EMU, EMU_to_pixels, short_color
class Shadow(object):
SHADOW_BOTTOM = 'b'
SHADOW_BOTTOM_LEFT = 'bl'
SHADOW_BOTTOM_RIGHT = 'br'
@@ -46,17 +46,17 @@ class Shadow(object):
self.alignment = self.SHADOW_BOTTOM_RIGHT
self.color = Color(Color.BLACK)
self.alpha = 50
class Drawing(object):
""" a drawing object - eg container for shapes or charts
we assume user specifies dimensions in pixels; units are
""" a drawing object - eg container for shapes or charts
we assume user specifies dimensions in pixels; units are
converted to EMU in the drawing part
"""
count = 0
def __init__(self):
self.name = ''
self.description = ''
self.coordinates = ((1,2), (16,8))
@@ -67,38 +67,38 @@ class Drawing(object):
self.resize_proportional = False
self.rotation = 0
# self.shadow = Shadow()
def _set_width(self, w):
if self.resize_proportional and w:
ratio = self._height / self._width
self._height = round(ratio * w)
self._width = w
def _get_width(self):
return self._width
width = property(_get_width, _set_width)
def _set_height(self, h):
if self.resize_proportional and h:
ratio = self._width / self._height
self._width = round(ratio * h)
self._height = h
def _get_height(self):
return self._height
height = property(_get_height, _set_height)
def set_dimension(self, w=0, h=0):
xratio = w / self._width
yratio = h / self._height
if self.resize_proportional and w and h:
if (xratio * self._height) < h:
self._height = math.ceil(xratio * self._height)
@@ -106,28 +106,28 @@ class Drawing(object):
else:
self._width = math.ceil(yratio * self._width)
self._height = height
def get_emu_dimensions(self):
""" return (x, y, w, h) in EMU """
return (pixels_to_EMU(self.left), pixels_to_EMU(self.top),
pixels_to_EMU(self._width), pixels_to_EMU(self._height))
class Shape(object):
""" a drawing inside a chart
coordiantes are specified by the user in the axis units
"""
MARGIN_LEFT = 6 + 13 + 1
MARGIN_BOTTOM = 17 + 11
FONT_WIDTH = 7
FONT_HEIGHT = 8
ROUND_RECT = 'roundRect'
RECT = 'rect'
# other shapes to define :
'''
"line"
@@ -317,9 +317,9 @@ class Shape(object):
"chartStar"
"chartPlus"
'''
def __init__(self, coordinates=((0,0), (1,1)), text=None, scheme="accent1"):
self.coordinates = coordinates # in axis unit
self.text = text
self.scheme = scheme
@@ -328,47 +328,47 @@ class Shape(object):
self._border_color = Color.BLACK[2:] #"F3B3C5"
self._color = Color.WHITE[2:]
self._text_color = Color.BLACK[2:]
def _get_border_color(self):
return self._border_color
def _set_border_color(self, color):
self._border_color = short_color(color)
border_color = property(_get_border_color, _set_border_color)
def _get_color(self):
return self._color
def _set_color(self, color):
self._color = short_color(color)
color = property(_get_color, _set_color)
def _get_text_color(self):
return self._text_color
def _set_text_color(self, color):
self._text_color = short_color(color)
text_color = property(_get_text_color, _set_text_color)
def _get_border_width(self):
return EMU_to_pixels(self._border_width)
def _set_border_width(self, w):
self._border_width = pixels_to_EMU(w)
print self._border_width
border_width = property(_get_border_width, _set_border_width)
def get_coordinates(self):
""" return shape coordinates in percentages (left, top, right, bottom) """
(x1, y1), (x2, y2) = self.coordinates
drawing_width = pixels_to_EMU(self._chart.drawing.width)
drawing_height = pixels_to_EMU(self._chart.drawing.height)
plot_width = drawing_width * self._chart.width
@@ -376,27 +376,26 @@ class Shape(object):
margin_left = self._chart._get_margin_left() * drawing_width
xunit = plot_width / self._chart.get_x_units()
margin_top = self._chart._get_margin_top() * drawing_height
yunit = self._chart.get_y_units()
x_start = (margin_left + (float(x1) * xunit)) / drawing_width
y_start = (margin_top + plot_height - (float(y1) * yunit)) / drawing_height
x_end = (margin_left + (float(x2) * xunit)) / drawing_width
y_end = (margin_top + plot_height - (float(y2) * yunit)) / drawing_height
def _norm_pct(pct):
""" force shapes to appear by truncating too large sizes """
if pct>1: pct = 1
elif pct<0: pct = 0
return pct
# allow user to specify y's in whatever order
# excel expect y_end to be lower
if y_end < y_start:
y_end, y_start = y_start, y_end
return (_norm_pct(x_start), _norm_pct(y_start),
return (_norm_pct(x_start), _norm_pct(y_start),
_norm_pct(x_end), _norm_pct(y_end))
+1 -1
View File
@@ -29,7 +29,7 @@
import re
# package imports
from openpyxl.shared.exc import NamedRangeException
from .shared.exc import NamedRangeException
# constants
NAMED_RANGE_RE = re.compile("'?([^']*)'?!((\$([A-Za-z]+))?\$([0-9]+)(:(\$([A-Za-z]+))?(\$([0-9]+)))?)$")
+5 -5
View File
@@ -26,8 +26,8 @@
"""Imports for the openpyxl.reader namespace."""
# package imports
from openpyxl.reader import excel
from openpyxl.reader import strings
from openpyxl.reader import style
from openpyxl.reader import workbook
from openpyxl.reader import worksheet
from ..reader import excel
from ..reader import strings
from ..reader import style
from ..reader import workbook
from ..reader import worksheet
+12 -12
View File
@@ -29,32 +29,32 @@
from zipfile import ZipFile, ZIP_DEFLATED, BadZipfile
# package imports
from openpyxl.shared.exc import OpenModeError, InvalidFileException
from openpyxl.shared.ooxml import ARC_SHARED_STRINGS, ARC_CORE, ARC_APP, \
from ..shared.exc import OpenModeError, InvalidFileException
from ..shared.ooxml import ARC_SHARED_STRINGS, ARC_CORE, ARC_APP, \
ARC_WORKBOOK, PACKAGE_WORKSHEETS, ARC_STYLE
from openpyxl.workbook import Workbook
from openpyxl.reader.strings import read_string_table
from openpyxl.reader.style import read_style_table
from openpyxl.reader.workbook import read_sheets_titles, read_named_ranges, \
from ..workbook import Workbook
from ..reader.strings import read_string_table
from ..reader.style import read_style_table
from ..reader.workbook import read_sheets_titles, read_named_ranges, \
read_properties_core, get_sheet_ids
from openpyxl.reader.worksheet import read_worksheet
from openpyxl.reader.iter_worksheet import unpack_worksheet
from ..reader.worksheet import read_worksheet
from ..reader.iter_worksheet import unpack_worksheet
def load_workbook(filename, use_iterators = False):
"""Open the given filename and return the workbook
:param filename: the path to open
:type filename: string
:param use_iterators: use lazy load for cells
:type use_iterators: bool
:rtype: :class:`openpyxl.workbook.Workbook`
.. note::
When using lazy load, all worksheets will be :class:`openpyxl.reader.iter_worksheet.IterableWorksheet`
and the returned workbook will be read-only.
and the returned workbook will be read-only.
"""
@@ -23,7 +23,7 @@
# @license: http://www.opensource.org/licenses/mit-license.php
# @author: Eric Gazoni
""" Iterators-based worksheet reader
""" Iterators-based worksheet reader
*Still very raw*
"""
@@ -32,18 +32,18 @@ import warnings
import operator
from functools import partial
from itertools import ifilter, groupby
from openpyxl.worksheet import Worksheet
from openpyxl.cell import coordinate_from_string, get_column_letter, Cell
from openpyxl.reader.excel import get_sheet_ids
from openpyxl.reader.strings import read_string_table
from openpyxl.reader.style import read_style_table, NumberFormat
from openpyxl.shared.date_time import SharedDate
from openpyxl.reader.worksheet import read_dimension
from openpyxl.shared.ooxml import (MIN_COLUMN, MAX_COLUMN, PACKAGE_WORKSHEETS,
from ..worksheet import Worksheet
from ..cell import coordinate_from_string, get_column_letter, Cell
from ..reader.excel import get_sheet_ids
from ..reader.strings import read_string_table
from ..reader.style import read_style_table, NumberFormat
from ..shared.date_time import SharedDate
from ..reader.worksheet import read_dimension
from ..shared.ooxml import (MIN_COLUMN, MAX_COLUMN, PACKAGE_WORKSHEETS,
MAX_ROW, MIN_ROW, ARC_SHARED_STRINGS, ARC_APP, ARC_STYLE)
from xml.etree.cElementTree import iterparse
from zipfile import ZipFile
import openpyxl.cell
from .. import cell
import re
import tempfile
import zlib
@@ -51,7 +51,7 @@ import zipfile
import struct
TYPE_NULL = Cell.TYPE_NULL
MISSING_VALUE = None
MISSING_VALUE = None
RE_COORDINATE = re.compile('^([A-Z]+)([0-9]+)$')
@@ -108,11 +108,11 @@ class RawCell(BaseRawCell):
def is_date(self):
res = (self.data_type == Cell.TYPE_NUMERIC
and self.number_format is not None
and ('d' in self.number_format
and ('d' in self.number_format
or 'm' in self.number_format
or 'y' in self.number_format
or 'h' in self.number_format
or 's' in self.number_format
or 's' in self.number_format
))
return res
@@ -121,7 +121,7 @@ def iter_rows(workbook_name, sheet_name, xml_source, range_string = '', row_offs
archive = get_archive_file(workbook_name)
source = xml_source
source = xml_source
if range_string:
min_col, min_row, max_col, max_row = get_range_boundaries(range_string, row_offset, column_offset)
@@ -187,7 +187,7 @@ def get_range_boundaries(range_string, row = 0, column = 0):
min_col, min_row = coordinate_from_string(range_string)
min_col = column_index_from_string(min_col)
max_col = min_col + 1
max_row = min_row
max_row = min_row
return (min_col, min_row, max_col, max_row)
@@ -215,7 +215,7 @@ def get_squared_range(p, min_col, min_row, max_col, max_row, string_table, style
for gap_row in xrange(current_row, row):
dummy_cells = get_missing_cells(gap_row, expected_columns)
yield tuple([dummy_cells[column] for column in expected_columns])
current_row = row
@@ -254,11 +254,11 @@ def get_squared_range(p, min_col, min_row, max_col, max_row, string_table, style
yield tuple(full_row)
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
class IterableWorksheet(Worksheet):
def __init__(self, parent_workbook, title, workbook_name,
def __init__(self, parent_workbook, title, workbook_name,
sheet_codename, xml_source):
Worksheet.__init__(self, parent_workbook, title)
@@ -267,20 +267,20 @@ class IterableWorksheet(Worksheet):
self._xml_source = xml_source
def iter_rows(self, range_string = '', row_offset = 0, column_offset = 0):
""" Returns a squared range based on the `range_string` parameter,
""" Returns a squared range based on the `range_string` parameter,
using generators.
:param range_string: range of cells (e.g. 'A1:C4')
:type range_string: string
:param row: row index of the cell (e.g. 4)
:type row: int
:param column: column index of the cell (e.g. 3)
:type column: int
:rtype: generator
"""
return iter_rows(workbook_name = self._workbook_name,
+2 -2
View File
@@ -26,8 +26,8 @@
"""Read the shared strings table."""
# package imports
from openpyxl.shared.xmltools import fromstring, QName
from openpyxl.shared.ooxml import NAMESPACES
from ..shared.xmltools import fromstring, QName
from ..shared.ooxml import NAMESPACES
def read_string_table(xml_source):
+3 -3
View File
@@ -26,9 +26,9 @@
"""Read shared style definitions"""
# package imports
from openpyxl.shared.xmltools import fromstring, QName
from openpyxl.shared.exc import MissingNumberFormat
from openpyxl.style import Style, NumberFormat
from ..shared.xmltools import fromstring, QName
from ..shared.exc import MissingNumberFormat
from ..style import Style, NumberFormat
def read_style_table(xml_source):
+5 -5
View File
@@ -26,11 +26,11 @@
"""Read in global settings to be maintained by the workbook object."""
# package imports
from openpyxl.shared.xmltools import fromstring, QName
from openpyxl.shared.ooxml import NAMESPACES
from openpyxl.workbook import DocumentProperties
from openpyxl.shared.date_time import W3CDTF_to_datetime
from openpyxl.namedrange import NamedRange, split_named_range
from ..shared.xmltools import fromstring, QName
from ..shared.ooxml import NAMESPACES
from ..workbook import DocumentProperties
from ..shared.date_time import W3CDTF_to_datetime
from ..namedrange import NamedRange, split_named_range
import datetime
+7 -7
View File
@@ -34,12 +34,12 @@ from itertools import ifilter
from StringIO import StringIO
# package imports
from openpyxl.cell import Cell, coordinate_from_string
from openpyxl.worksheet import Worksheet
from ..cell import Cell, coordinate_from_string
from ..worksheet import Worksheet
def _get_xml_iter(xml_source):
if not hasattr(xml_source, 'name'):
if not hasattr(xml_source, 'name'):
return StringIO(xml_source)
else:
xml_source.seek(0)
@@ -47,7 +47,7 @@ def _get_xml_iter(xml_source):
def read_dimension(xml_source):
source = _get_xml_iter(xml_source)
source = _get_xml_iter(xml_source)
it = iterparse(source)
@@ -73,7 +73,7 @@ def filter_cells((event, element)):
def fast_parse(ws, xml_source, string_table, style_table):
source = _get_xml_iter(xml_source)
source = _get_xml_iter(xml_source)
it = iterparse(source)
@@ -98,13 +98,13 @@ def fast_parse(ws, xml_source, string_table, style_table):
# to avoid memory exhaustion, clear the item after use
element.clear()
from openpyxl.reader.iter_worksheet import IterableWorksheet
from ..reader.iter_worksheet import IterableWorksheet
def read_worksheet(xml_source, parent, preset_title, string_table,
style_table, workbook_name = None, sheet_codename = None):
"""Read an xml worksheet"""
if workbook_name and sheet_codename:
ws = IterableWorksheet(parent, preset_title, workbook_name,
ws = IterableWorksheet(parent, preset_title, workbook_name,
sheet_codename, xml_source)
else:
ws = Worksheet(parent, preset_title)
+5 -5
View File
@@ -26,8 +26,8 @@
"""Imports for the openpyxl.shared namespace."""
# package imports
from openpyxl.shared import date_time
from openpyxl.shared import exc
from openpyxl.shared import ooxml
from openpyxl.shared import password_hasher
from openpyxl.shared import xmltools
from . import date_time
from . import exc
from . import ooxml
from . import password_hasher
from . import xmltools
+1 -1
View File
@@ -41,7 +41,7 @@ except ImportError:
QName, fromstring, tostring
# package imports
from openpyxl import __name__ as prefix
from .. import __name__ as prefix
def get_document_content(xml_node):
+7 -7
View File
@@ -32,13 +32,13 @@ import datetime
import os
# package imports
from openpyxl.worksheet import Worksheet
from openpyxl.writer.dump_worksheet import DumpWorksheet, save_dump
from openpyxl.writer.strings import StringTableBuilder
from openpyxl.namedrange import NamedRange
from openpyxl.style import Style
from openpyxl.writer.excel import save_workbook
from openpyxl.shared.exc import ReadOnlyWorkbookException
from .worksheet import Worksheet
from .writer.dump_worksheet import DumpWorksheet, save_dump
from .writer.strings import StringTableBuilder
from .namedrange import NamedRange
from .style import Style
from .writer.excel import save_workbook
from .shared.exc import ReadOnlyWorkbookException
class DocumentProperties(object):
+15 -15
View File
@@ -29,15 +29,15 @@
import re
# package imports
import openpyxl.cell
from openpyxl.cell import coordinate_from_string, \
from . import cell
from .cell import coordinate_from_string, \
column_index_from_string, get_column_letter
from openpyxl.shared.exc import SheetTitleException, \
from .shared.exc import SheetTitleException, \
InsufficientCoordinatesException, CellCoordinatesException, \
NamedRangeException
from openpyxl.shared.password_hasher import hash_password
from openpyxl.style import Style, DEFAULTS as DEFAULTS_STYLE
from openpyxl.drawing import Drawing
from .shared.password_hasher import hash_password
from .style import Style, DEFAULTS as DEFAULTS_STYLE
from .drawing import Drawing
_DEFAULTS_STYLE_HASH = hash(DEFAULTS_STYLE)
@@ -344,7 +344,7 @@ class Worksheet(object):
if not coordinate in self._cells:
column, row = coordinate_from_string(coordinate)
new_cell = openpyxl.cell.Cell(self, column, row)
new_cell = cell.Cell(self, column, row)
self._cells[coordinate] = new_cell
if column not in self.column_dimensions:
self.column_dimensions[column] = ColumnDimension(column)
@@ -354,7 +354,7 @@ class Worksheet(object):
def get_highest_row(self):
"""Returns the maximum row index containing data
:rtype: int
"""
if self.row_dimensions:
@@ -364,7 +364,7 @@ class Worksheet(object):
def get_highest_column(self):
"""Get the largest value for column currently stored.
:rtype: int
"""
if self.column_dimensions:
@@ -475,21 +475,21 @@ class Worksheet(object):
def append(self, list_or_dict):
"""Appends a group of values at the bottom of the current sheet.
* If it's a list: all values are added in order, starting from the first column
* If it's a dict: values are assigned to the columns indicated by the keys (numbers or letters)
:param list_or_dict: list or dict containing values to append
:type list_or_dict: list/tuple or dict
Usage:
* append(['This is A1', 'This is B1', 'This is C1'])
* **or** append({'A' : 'This is A1', 'C' : 'This is C1'})
* **or** append({0 : 'This is A1', 2 : 'This is C1'})
:raise: TypeError when list_or_dict is neither a list/tuple nor a dict
"""
row_idx = len(self.row_dimensions)
+6 -6
View File
@@ -26,9 +26,9 @@
"""Imports for the openpyxl.writer namespace."""
# package imports
from openpyxl.writer import excel
from openpyxl.writer import strings
from openpyxl.writer import styles
from openpyxl.writer import theme
from openpyxl.writer import workbook
from openpyxl.writer import worksheet
from . import excel
from . import strings
from . import styles
from . import theme
from . import workbook
from . import worksheet
+44 -44
View File
@@ -24,33 +24,33 @@ THE SOFTWARE.
@author: Eric Gazoni
'''
from openpyxl.shared.xmltools import Element, SubElement, get_document_content
from openpyxl.chart import Chart, ErrorBar
from ..shared.xmltools import Element, SubElement, get_document_content
from ..chart import Chart, ErrorBar
class ChartWriter(object):
def __init__(self, chart):
self.chart = chart
def write(self):
""" write a chart """
root = Element('c:chartSpace',
root = Element('c:chartSpace',
{'xmlns:c':"http://schemas.openxmlformats.org/drawingml/2006/chart",
'xmlns:a':"http://schemas.openxmlformats.org/drawingml/2006/main",
'xmlns:r':"http://schemas.openxmlformats.org/officeDocument/2006/relationships"})
SubElement(root, 'c:lang', {'val':self.chart.lang})
self._write_chart(root)
self._write_print_settings(root)
self._write_shapes(root)
return get_document_content(root)
def _write_chart(self, root):
chart = self.chart
ch = SubElement(root, 'c:chart')
self._write_title(ch)
plot_area = SubElement(ch, 'c:plotArea')
@@ -63,7 +63,7 @@ class ChartWriter(object):
SubElement(mlayout, 'c:y', {'val':str(chart._get_margin_top())})
SubElement(mlayout, 'c:w', {'val':str(chart.width)})
SubElement(mlayout, 'c:h', {'val':str(chart.height)})
if chart.type == Chart.SCATTER_CHART:
subchart = SubElement(plot_area, 'c:scatterChart')
SubElement(subchart, 'c:scatterStyle', {'val':str('lineMarker')})
@@ -73,23 +73,23 @@ class ChartWriter(object):
SubElement(subchart, 'c:barDir', {'val':'col'})
else:
subchart = SubElement(plot_area, 'c:lineChart')
SubElement(subchart, 'c:grouping', {'val':chart.grouping})
self._write_series(subchart)
SubElement(subchart, 'c:marker', {'val':'1'})
SubElement(subchart, 'c:axId', {'val':str(chart.x_axis.id)})
SubElement(subchart, 'c:axId', {'val':str(chart.y_axis.id)})
if chart.type == Chart.SCATTER_CHART:
self._write_axis(plot_area, chart.x_axis, 'c:valAx')
else:
self._write_axis(plot_area, chart.x_axis, 'c:catAx')
self._write_axis(plot_area, chart.y_axis, 'c:valAx')
self._write_legend(ch)
SubElement(ch, 'c:plotVisOnly', {'val':'1'})
def _write_title(self, chart):
@@ -108,16 +108,16 @@ class ChartWriter(object):
SubElement(title, 'c:layout')
def _write_axis(self, plot_area, axis, label):
ax = SubElement(plot_area, label)
SubElement(ax, 'c:axId', {'val':str(axis.id)})
scaling = SubElement(ax, 'c:scaling')
SubElement(scaling, 'c:orientation', {'val':axis.orientation})
if label == 'c:valAx':
SubElement(scaling, 'c:max', {'val':str(axis.max)})
SubElement(scaling, 'c:min', {'val':str(axis.min)})
SubElement(ax, 'c:axPos', {'val':axis.position})
if label == 'c:valAx':
SubElement(ax, 'c:majorGridlines')
@@ -137,18 +137,18 @@ class ChartWriter(object):
else:
SubElement(ax, 'c:crossBetween', {'val':'between'})
SubElement(ax, 'c:majorUnit', {'val':str(axis.unit)})
def _write_series(self, subchart):
for i, serie in enumerate(self.chart._series):
ser = SubElement(subchart, 'c:ser')
SubElement(ser, 'c:idx', {'val':str(i)})
SubElement(ser, 'c:order', {'val':str(i)})
if serie.legend:
tx = SubElement(ser, 'c:tx')
self._write_serial(tx, serie.legend)
if serie.color:
sppr = SubElement(ser, 'c:spPr')
if self.chart.type == Chart.BAR_CHART:
@@ -159,17 +159,17 @@ class ChartWriter(object):
ln = SubElement(sppr, 'a:ln')
fill = SubElement(ln, 'a:solidFill')
SubElement(fill, 'a:srgbClr', {'val':serie.color})
if serie.error_bar:
self._write_error_bar(ser, serie)
marker = SubElement(ser, 'c:marker')
SubElement(marker, 'c:symbol', {'val':serie.marker})
if serie.labels:
cat = SubElement(ser, 'c:cat')
self._write_serial(cat, serie.labels)
if self.chart.type == Chart.SCATTER_CHART:
if serie.xvalues:
xval = SubElement(ser, 'c:xVal')
@@ -180,7 +180,7 @@ class ChartWriter(object):
else:
val = SubElement(ser, 'c:val')
self._write_serial(val, serie.values)
def _write_serial(self, node, serie, literal=False):
cache = serie._get_cache()
@@ -188,7 +188,7 @@ class ChartWriter(object):
typ = 'str'
else:
typ = 'num'
if not literal:
if typ == 'num':
ref = SubElement(node, 'c:numRef')
@@ -208,51 +208,51 @@ class ChartWriter(object):
values = (1,)
else:
values = cache
SubElement(data, 'c:ptCount', {'val':str(len(values))})
for j, val in enumerate(values):
point = SubElement(data, 'c:pt', {'idx':str(j)})
SubElement(point, 'c:v').text = str(val)
def _write_error_bar(self, node, serie):
flag = {ErrorBar.PLUS_MINUS:'both',
ErrorBar.PLUS:'plus',
flag = {ErrorBar.PLUS_MINUS:'both',
ErrorBar.PLUS:'plus',
ErrorBar.MINUS:'minus'}
eb = SubElement(node, 'c:errBars')
SubElement(eb, 'c:errBarType', {'val':flag[serie.error_bar.type]})
SubElement(eb, 'c:errValType', {'val':'cust'})
plus = SubElement(eb, 'c:plus')
self._write_serial(plus, serie.error_bar.values,
literal=(serie.error_bar.type==ErrorBar.MINUS))
minus = SubElement(eb, 'c:minus')
self._write_serial(minus, serie.error_bar.values,
literal=(serie.error_bar.type==ErrorBar.PLUS))
def _write_legend(self, chart):
legend = SubElement(chart, 'c:legend')
SubElement(legend, 'c:legendPos', {'val':self.chart.legend.position})
SubElement(legend, 'c:layout')
def _write_print_settings(self, root):
settings = SubElement(root, 'c:printSettings')
SubElement(settings, 'c:headerFooter')
margins = dict([(k, str(v)) for (k,v) in self.chart.print_margins.iteritems()])
SubElement(settings, 'c:pageMargins', margins)
SubElement(settings, 'c:pageSetup')
def _write_shapes(self, root):
if self.chart._shapes:
SubElement(root, 'c:userShapes', {'r:id':'rId1'})
def write_rels(self, drawing_id):
root = Element('Relationships', {'xmlns' : 'http://schemas.openxmlformats.org/package/2006/relationships'})
attrs = {'Id' : 'rId1',
'Type' : 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chartUserShapes',
+1 -1
View File
@@ -24,7 +24,7 @@ THE SOFTWARE.
@author: Eric Gazoni
'''
from openpyxl.shared.xmltools import Element, SubElement, get_document_content
from ..shared.xmltools import Element, SubElement, get_document_content
class DrawingWriter(object):
@@ -28,19 +28,19 @@
import datetime
import os
from openpyxl.cell import column_index_from_string, get_column_letter, Cell
from openpyxl.worksheet import Worksheet
from openpyxl.shared.xmltools import XMLGenerator, get_document_content, \
from ..cell import column_index_from_string, get_column_letter, Cell
from ..worksheet import Worksheet
from ..shared.xmltools import XMLGenerator, get_document_content, \
start_tag, end_tag, tag
from openpyxl.shared.date_time import SharedDate
from openpyxl.shared.ooxml import MAX_COLUMN, MAX_ROW
from ..shared.date_time import SharedDate
from ..shared.ooxml import MAX_COLUMN, MAX_ROW
from tempfile import NamedTemporaryFile
from openpyxl.writer.excel import ExcelWriter
from openpyxl.writer.strings import write_string_table
from openpyxl.writer.styles import StyleWriter
from openpyxl.style import Style, NumberFormat
from ..writer.excel import ExcelWriter
from ..writer.strings import write_string_table
from ..writer.styles import StyleWriter
from ..style import Style, NumberFormat
from openpyxl.shared.ooxml import ARC_SHARED_STRINGS, ARC_CONTENT_TYPES, \
from ..shared.ooxml import ARC_SHARED_STRINGS, ARC_CONTENT_TYPES, \
ARC_ROOT_RELS, ARC_WORKBOOK_RELS, ARC_APP, ARC_CORE, ARC_THEME, \
ARC_STYLE, ARC_WORKBOOK, \
PACKAGE_WORKSHEETS, PACKAGE_DRAWINGS, PACKAGE_CHARTS
@@ -58,7 +58,7 @@ STYLES = {'datetime' : {'type':Cell.TYPE_NUMERIC,
}
DATETIME_STYLE = Style()
DATETIME_STYLE.number_format.format_code = NumberFormat.FORMAT_DATE_YYYYMMDD2
DATETIME_STYLE.number_format.format_code = NumberFormat.FORMAT_DATE_YYYYMMDD2
BOUNDING_BOX_PLACEHOLDER = 'A1:%s%d' % (get_column_letter(MAX_COLUMN), MAX_ROW)
class DumpWorksheet(Worksheet):
@@ -66,7 +66,7 @@ class DumpWorksheet(Worksheet):
"""
.. warning::
You shouldn't initialize this yourself, use :class:`openpyxl.workbook.Workbook` constructor instead,
You shouldn't initialize this yourself, use :class:`openpyxl.workbook.Workbook` constructor instead,
with `optimized_write = True`.
"""
@@ -101,7 +101,7 @@ class DumpWorksheet(Worksheet):
'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'})
start_tag(doc, 'sheetPr')
tag(doc, 'outlinePr',
{'summaryBelow': '1',
{'summaryBelow': '1',
'summaryRight': '1'})
end_tag(doc, 'sheetPr')
tag(doc, 'dimension', {'ref': 'A1:%s' % (self.get_dimensions())})
@@ -141,7 +141,7 @@ class DumpWorksheet(Worksheet):
self._fileobj.flush()
def _close_header(self):
doc = self.header
#doc.endDocument()
@@ -159,7 +159,7 @@ class DumpWorksheet(Worksheet):
return 'A1'
else:
return '%s%d' % (get_column_letter(self._max_col), (self._max_row))
def append(self, row):
"""
@@ -185,7 +185,7 @@ class DumpWorksheet(Worksheet):
if cell is None:
continue
coordinate = '%s%d' % (get_column_letter(col_idx+1), row_idx)
coordinate = '%s%d' % (get_column_letter(col_idx+1), row_idx)
attributes = {'r': coordinate}
if isinstance(cell, bool):
@@ -211,7 +211,7 @@ class DumpWorksheet(Worksheet):
tag(doc, 'v')
else:
tag(doc, 'v', body = '%s' % cell)
end_tag(doc, 'c')
@@ -253,4 +253,4 @@ class StyleDumpWriter(StyleWriter):
def _get_style_list(self, workbook):
return []
+9 -9
View File
@@ -30,19 +30,19 @@ from zipfile import ZipFile, ZIP_DEFLATED
from StringIO import StringIO
# package imports
from openpyxl.shared.ooxml import ARC_SHARED_STRINGS, ARC_CONTENT_TYPES, \
from ..shared.ooxml import ARC_SHARED_STRINGS, ARC_CONTENT_TYPES, \
ARC_ROOT_RELS, ARC_WORKBOOK_RELS, ARC_APP, ARC_CORE, ARC_THEME, \
ARC_STYLE, ARC_WORKBOOK, \
PACKAGE_WORKSHEETS, PACKAGE_DRAWINGS, PACKAGE_CHARTS
from openpyxl.writer.strings import create_string_table, write_string_table
from openpyxl.writer.workbook import write_content_types, write_root_rels, \
from ..writer.strings import create_string_table, write_string_table
from ..writer.workbook import write_content_types, write_root_rels, \
write_workbook_rels, write_properties_app, write_properties_core, \
write_workbook
from openpyxl.writer.theme import write_theme
from openpyxl.writer.styles import StyleWriter
from openpyxl.writer.drawings import DrawingWriter, ShapeWriter
from openpyxl.writer.charts import ChartWriter
from openpyxl.writer.worksheet import write_worksheet, write_worksheet_rels
from ..writer.theme import write_theme
from ..writer.styles import StyleWriter
from ..writer.drawings import DrawingWriter, ShapeWriter
from ..writer.charts import ChartWriter
from ..writer.worksheet import write_worksheet, write_worksheet_rels
class ExcelWriter(object):
@@ -56,7 +56,7 @@ class ExcelWriter(object):
"""Write the various xml files into the zip archive."""
# cleanup all worksheets
shared_string_table = self._write_string_table(archive)
archive.writestr(ARC_CONTENT_TYPES, write_content_types(self.workbook))
archive.writestr(ARC_ROOT_RELS, write_root_rels(self.workbook))
archive.writestr(ARC_WORKBOOK_RELS, write_workbook_rels(self.workbook))
+1 -1
View File
@@ -29,7 +29,7 @@
from StringIO import StringIO
# package imports
from openpyxl.shared.xmltools import start_tag, end_tag, tag, XMLGenerator
from ..shared.xmltools import start_tag, end_tag, tag, XMLGenerator
def create_string_table(workbook):
+31 -31
View File
@@ -26,17 +26,17 @@
"""Write the shared style table."""
# package imports
from openpyxl.shared.xmltools import Element, SubElement
from openpyxl.shared.xmltools import get_document_content
from openpyxl import style
from ..shared.xmltools import Element, SubElement
from ..shared.xmltools import get_document_content
from .. import style
class StyleWriter(object):
def __init__(self, workbook):
self._style_list = self._get_style_list(workbook)
self._root = Element('styleSheet',
self._root = Element('styleSheet',
{'xmlns':'http://schemas.openxmlformats.org/spreadsheetml/2006/main'})
def _get_style_list(self, workbook):
crc = {}
for worksheet in workbook.worksheets:
@@ -51,7 +51,7 @@ class StyleWriter(object):
def get_style_by_hash(self):
return dict([(hash(style), id) \
for style, id in self.style_table.iteritems()])
def write_table(self):
number_format_table = self._write_number_formats()
fonts_table = self._write_fonts()
@@ -71,7 +71,7 @@ class StyleWriter(object):
"""
fonts = SubElement(self._root, 'fonts')
# default
font_node = SubElement(fonts, 'font')
SubElement(font_node, 'sz', {'val':'11'})
@@ -79,7 +79,7 @@ class StyleWriter(object):
SubElement(font_node, 'name', {'val':'Calibri'})
SubElement(font_node, 'family', {'val':'2'})
SubElement(font_node, 'scheme', {'val':'minor'})
# others
table = {}
index = 1
@@ -97,7 +97,7 @@ class StyleWriter(object):
if st.font.italic:
SubElement(font_node, 'i')
index += 1
fonts.attrib["count"] = str(index)
return table
@@ -122,7 +122,7 @@ class StyleWriter(object):
if hash(st.fill.end_color) != hash(style.DEFAULTS.fill.end_color):
SubElement(node, 'bgColor', {'rgb':str(st.fill.start_color.index)})
index += 1
fills.attrib["count"] = str(index)
return table
@@ -136,7 +136,7 @@ class StyleWriter(object):
SubElement(border, 'top')
SubElement(border, 'bottom')
SubElement(border, 'diagonal')
# others
table = {}
index = 1
@@ -150,40 +150,40 @@ class StyleWriter(object):
node = SubElement(border, side, {'style':obj.border_style})
SubElement(node, 'color', {'rgb':str(obj.color.index)})
index += 1
borders.attrib["count"] = str(index)
return table
def _write_cell_style_xfs(self):
cell_style_xfs = SubElement(self._root, 'cellStyleXfs', {'count':'1'})
xf = SubElement(cell_style_xfs, 'xf',
xf = SubElement(cell_style_xfs, 'xf',
{'numFmtId':"0", 'fontId':"0", 'fillId':"0", 'borderId':"0"})
def _write_cell_xfs(self, number_format_table, fonts_table, fills_table, borders_table):
""" write styles combinations based on ids found in tables """
# writing the cellXfs
cell_xfs = SubElement(self._root, 'cellXfs',
cell_xfs = SubElement(self._root, 'cellXfs',
{'count':'%d' % (len(self._style_list) + 1)})
# default
def _get_default_vals():
return dict(numFmtId='0', fontId='0', fillId='0',
return dict(numFmtId='0', fontId='0', fillId='0',
xfId='0', borderId='0')
SubElement(cell_xfs, 'xf', _get_default_vals())
for st in self._style_list:
vals = _get_default_vals()
if hash(st.font) != hash(style.DEFAULTS.font):
vals['fontId'] = fonts_table[hash(st.font)]
vals['applyFont'] = '1'
if hash(st.borders) != hash(style.DEFAULTS.borders):
vals['borderId'] = borders_table[hash(st.borders)]
vals['applyBorder'] = '1'
if hash(st.fill) != hash(style.DEFAULTS.fill):
vals['fillId'] = fills_table[hash(st.fill)]
vals['applyFillId'] = '1'
@@ -191,7 +191,7 @@ class StyleWriter(object):
if st.number_format != style.DEFAULTS.number_format:
vals['numFmtId'] = '%d' % number_format_table[st.number_format]
vals['applyNumberFormat'] = '1'
if hash(st.alignment) != hash(style.DEFAULTS.alignment):
vals['applyAlignment'] = '1'
@@ -209,7 +209,7 @@ class StyleWriter(object):
def _write_cell_style(self):
cell_styles = SubElement(self._root, 'cellStyles', {'count':'1'})
cell_style = SubElement(cell_styles, 'cellStyle',
cell_style = SubElement(cell_styles, 'cellStyle',
{'name':"Normal", 'xfId':"0", 'builtinId':"0"})
def _write_dxfs(self):
@@ -217,7 +217,7 @@ class StyleWriter(object):
def _write_table_styles(self):
table_styles = SubElement(self._root, 'tableStyles',
table_styles = SubElement(self._root, 'tableStyles',
{'count':'0', 'defaultTableStyle':'TableStyleMedium9',
'defaultPivotStyle':'PivotStyleLight16'})
@@ -245,12 +245,12 @@ class StyleWriter(object):
num_fmt_offset += 1
exceptions_list.append(number_format)
num_fmts = SubElement(self._root, 'numFmts',
num_fmts = SubElement(self._root, 'numFmts',
{'count':'%d' % len(exceptions_list)})
for number_format in exceptions_list :
SubElement(num_fmts, 'numFmt',
SubElement(num_fmts, 'numFmt',
{'numFmtId':'%d' % number_format_table[number_format],
'formatCode':'%s' % number_format.format_code})
'formatCode':'%s' % number_format.format_code})
return number_format_table
+1 -1
View File
@@ -27,7 +27,7 @@
"""Write the theme xml based on a fixed string."""
# package imports
from openpyxl.shared.xmltools import fromstring, get_document_content
from ..shared.xmltools import fromstring, get_document_content
def write_theme():
+5 -5
View File
@@ -26,12 +26,12 @@
"""Write the workbook global settings to the archive."""
# package imports
from openpyxl.shared.xmltools import Element, SubElement
from openpyxl.cell import absolute_coordinate
from openpyxl.shared.xmltools import get_document_content
from openpyxl.shared.ooxml import NAMESPACES, ARC_CORE, ARC_WORKBOOK, \
from ..shared.xmltools import Element, SubElement
from ..cell import absolute_coordinate
from ..shared.xmltools import get_document_content
from ..shared.ooxml import NAMESPACES, ARC_CORE, ARC_WORKBOOK, \
ARC_APP, ARC_THEME, ARC_STYLE, ARC_SHARED_STRINGS
from openpyxl.shared.date_time import datetime_to_W3CDTF
from ..shared.date_time import datetime_to_W3CDTF
def write_properties_core(properties):
+3 -3
View File
@@ -29,8 +29,8 @@
from StringIO import StringIO # cStringIO doesn't handle unicode
# package imports
from openpyxl.cell import coordinate_from_string, column_index_from_string
from openpyxl.shared.xmltools import Element, SubElement, XMLGenerator, \
from ..cell import coordinate_from_string, column_index_from_string
from ..shared.xmltools import Element, SubElement, XMLGenerator, \
get_document_content, start_tag, end_tag, tag
@@ -100,7 +100,7 @@ def write_worksheet_sheetviews(doc, worksheet):
tag(doc, 'selection', selectionAttrs)
end_tag(doc, 'sheetView')
end_tag(doc, 'sheetViews')
def write_worksheet_cols(doc, worksheet):
"""Write worksheet columns to xml."""