mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-07-02 14:27:31 +00:00
Version 0.1
Added sidebar, Dashboard, Line Graph
This commit is contained in:
17
.venv/Lib/site-packages/openpyxl/utils/__init__.py
Normal file
17
.venv/Lib/site-packages/openpyxl/utils/__init__.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
|
||||
from .cell import (
|
||||
absolute_coordinate,
|
||||
cols_from_range,
|
||||
column_index_from_string,
|
||||
coordinate_to_tuple,
|
||||
get_column_letter,
|
||||
get_column_interval,
|
||||
quote_sheetname,
|
||||
range_boundaries,
|
||||
range_to_tuple,
|
||||
rows_from_range,
|
||||
)
|
||||
|
||||
from .formulas import FORMULAE
|
26
.venv/Lib/site-packages/openpyxl/utils/bound_dictionary.py
Normal file
26
.venv/Lib/site-packages/openpyxl/utils/bound_dictionary.py
Normal file
@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class BoundDictionary(defaultdict):
|
||||
"""
|
||||
A default dictionary where elements are tightly coupled.
|
||||
|
||||
The factory method is responsible for binding the parent object to the child.
|
||||
|
||||
If a reference attribute is assigned then child objects will have the key assigned to this.
|
||||
|
||||
Otherwise it's just a defaultdict.
|
||||
"""
|
||||
|
||||
def __init__(self, reference=None, *args, **kw):
|
||||
self.reference = reference
|
||||
super(BoundDictionary, self).__init__(*args, **kw)
|
||||
|
||||
|
||||
def __getitem__(self, key):
|
||||
value = super(BoundDictionary, self).__getitem__(key)
|
||||
if self.reference is not None:
|
||||
setattr(value, self.reference, key)
|
||||
return value
|
227
.venv/Lib/site-packages/openpyxl/utils/cell.py
Normal file
227
.venv/Lib/site-packages/openpyxl/utils/cell.py
Normal file
@ -0,0 +1,227 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
"""
|
||||
Collection of utilities used within the package and also available for client code
|
||||
"""
|
||||
import re
|
||||
from string import digits
|
||||
|
||||
from .exceptions import CellCoordinatesException
|
||||
|
||||
# constants
|
||||
COORD_RE = re.compile(r'^[$]?([A-Za-z]{1,3})[$]?(\d+)$')
|
||||
COL_RANGE = """[A-Z]{1,3}:[A-Z]{1,3}:"""
|
||||
ROW_RANGE = r"""\d+:\d+:"""
|
||||
RANGE_EXPR = r"""
|
||||
[$]?(?P<min_col>[A-Za-z]{1,3})?
|
||||
[$]?(?P<min_row>\d+)?
|
||||
(:[$]?(?P<max_col>[A-Za-z]{1,3})?
|
||||
[$]?(?P<max_row>\d+)?)?
|
||||
"""
|
||||
ABSOLUTE_RE = re.compile('^' + RANGE_EXPR +'$', re.VERBOSE)
|
||||
SHEET_TITLE = r"""
|
||||
(('(?P<quoted>([^']|'')*)')|(?P<notquoted>[^'^ ^!]*))!"""
|
||||
SHEETRANGE_RE = re.compile("""{0}(?P<cells>{1})(?=,?)""".format(
|
||||
SHEET_TITLE, RANGE_EXPR), re.VERBOSE)
|
||||
|
||||
|
||||
def get_column_interval(start, end):
|
||||
"""
|
||||
Given the start and end columns, return all the columns in the series.
|
||||
|
||||
The start and end columns can be either column letters or 1-based
|
||||
indexes.
|
||||
"""
|
||||
if isinstance(start, str):
|
||||
start = column_index_from_string(start)
|
||||
if isinstance(end, str):
|
||||
end = column_index_from_string(end)
|
||||
return [get_column_letter(x) for x in range(start, end + 1)]
|
||||
|
||||
|
||||
def coordinate_from_string(coord_string):
|
||||
"""Convert a coordinate string like 'B12' to a tuple ('B', 12)"""
|
||||
match = COORD_RE.match(coord_string)
|
||||
if not match:
|
||||
msg = f"Invalid cell coordinates ({coord_string})"
|
||||
raise CellCoordinatesException(msg)
|
||||
column, row = match.groups()
|
||||
row = int(row)
|
||||
if not row:
|
||||
msg = f"There is no row 0 ({coord_string})"
|
||||
raise CellCoordinatesException(msg)
|
||||
return column, row
|
||||
|
||||
|
||||
def absolute_coordinate(coord_string):
|
||||
"""Convert a coordinate to an absolute coordinate string (B12 -> $B$12)"""
|
||||
m = ABSOLUTE_RE.match(coord_string)
|
||||
if not m:
|
||||
raise ValueError(f"{coord_string} is not a valid coordinate range")
|
||||
|
||||
d = m.groupdict('')
|
||||
for k, v in d.items():
|
||||
if v:
|
||||
d[k] = f"${v}"
|
||||
|
||||
if d['max_col'] or d['max_row']:
|
||||
fmt = "{min_col}{min_row}:{max_col}{max_row}"
|
||||
else:
|
||||
fmt = "{min_col}{min_row}"
|
||||
return fmt.format(**d)
|
||||
|
||||
|
||||
def _get_column_letter(col_idx):
|
||||
"""Convert a column number into a column letter (3 -> 'C')
|
||||
|
||||
Right shift the column col_idx by 26 to find column letters in reverse
|
||||
order. These numbers are 1-based, and can be converted to ASCII
|
||||
ordinals by adding 64.
|
||||
|
||||
"""
|
||||
# these indicies corrospond to A -> ZZZ and include all allowed
|
||||
# columns
|
||||
if not 1 <= col_idx <= 18278:
|
||||
raise ValueError("Invalid column index {0}".format(col_idx))
|
||||
letters = []
|
||||
while col_idx > 0:
|
||||
col_idx, remainder = divmod(col_idx, 26)
|
||||
# check for exact division and borrow if needed
|
||||
if remainder == 0:
|
||||
remainder = 26
|
||||
col_idx -= 1
|
||||
letters.append(chr(remainder+64))
|
||||
return ''.join(reversed(letters))
|
||||
|
||||
|
||||
_COL_STRING_CACHE = {}
|
||||
_STRING_COL_CACHE = {}
|
||||
for i in range(1, 18279):
|
||||
col = _get_column_letter(i)
|
||||
_STRING_COL_CACHE[i] = col
|
||||
_COL_STRING_CACHE[col] = i
|
||||
|
||||
|
||||
def get_column_letter(idx,):
|
||||
"""Convert a column index into a column letter
|
||||
(3 -> 'C')
|
||||
"""
|
||||
try:
|
||||
return _STRING_COL_CACHE[idx]
|
||||
except KeyError:
|
||||
raise ValueError("Invalid column index {0}".format(idx))
|
||||
|
||||
|
||||
def column_index_from_string(str_col):
|
||||
"""Convert a column name into a numerical index
|
||||
('A' -> 1)
|
||||
"""
|
||||
# we use a function argument to get indexed name lookup
|
||||
try:
|
||||
return _COL_STRING_CACHE[str_col.upper()]
|
||||
except KeyError:
|
||||
raise ValueError("{0} is not a valid column name".format(str_col))
|
||||
|
||||
|
||||
def range_boundaries(range_string):
|
||||
"""
|
||||
Convert a range string into a tuple of boundaries:
|
||||
(min_col, min_row, max_col, max_row)
|
||||
Cell coordinates will be converted into a range with the cell at both end
|
||||
"""
|
||||
msg = "{0} is not a valid coordinate or range".format(range_string)
|
||||
m = ABSOLUTE_RE.match(range_string)
|
||||
if not m:
|
||||
raise ValueError(msg)
|
||||
|
||||
min_col, min_row, sep, max_col, max_row = m.groups()
|
||||
|
||||
if sep:
|
||||
cols = min_col, max_col
|
||||
rows = min_row, max_row
|
||||
|
||||
if not (
|
||||
all(cols + rows) or
|
||||
all(cols) and not any(rows) or
|
||||
all(rows) and not any(cols)
|
||||
):
|
||||
raise ValueError(msg)
|
||||
|
||||
if min_col is not None:
|
||||
min_col = column_index_from_string(min_col)
|
||||
|
||||
if min_row is not None:
|
||||
min_row = int(min_row)
|
||||
|
||||
if max_col is not None:
|
||||
max_col = column_index_from_string(max_col)
|
||||
else:
|
||||
max_col = min_col
|
||||
|
||||
if max_row is not None:
|
||||
max_row = int(max_row)
|
||||
else:
|
||||
max_row = min_row
|
||||
|
||||
return min_col, min_row, max_col, max_row
|
||||
|
||||
|
||||
def rows_from_range(range_string):
|
||||
"""
|
||||
Get individual addresses for every cell in a range.
|
||||
Yields one row at a time.
|
||||
"""
|
||||
min_col, min_row, max_col, max_row = range_boundaries(range_string)
|
||||
rows = range(min_row, max_row + 1)
|
||||
cols = [get_column_letter(col) for col in range(min_col, max_col + 1)]
|
||||
for row in rows:
|
||||
yield tuple('{0}{1}'.format(col, row) for col in cols)
|
||||
|
||||
|
||||
def cols_from_range(range_string):
|
||||
"""
|
||||
Get individual addresses for every cell in a range.
|
||||
Yields one row at a time.
|
||||
"""
|
||||
min_col, min_row, max_col, max_row = range_boundaries(range_string)
|
||||
rows = range(min_row, max_row+1)
|
||||
cols = (get_column_letter(col) for col in range(min_col, max_col+1))
|
||||
for col in cols:
|
||||
yield tuple('{0}{1}'.format(col, row) for row in rows)
|
||||
|
||||
|
||||
def coordinate_to_tuple(coordinate):
|
||||
"""
|
||||
Convert an Excel style coordinate to (row, colum) tuple
|
||||
"""
|
||||
for idx, c in enumerate(coordinate):
|
||||
if c in digits:
|
||||
break
|
||||
col = coordinate[:idx].upper()
|
||||
row = coordinate[idx:]
|
||||
return int(row), _COL_STRING_CACHE[col]
|
||||
|
||||
|
||||
def range_to_tuple(range_string):
|
||||
"""
|
||||
Convert a worksheet range to the sheetname and maximum and minimum
|
||||
coordinate indices
|
||||
"""
|
||||
m = SHEETRANGE_RE.match(range_string)
|
||||
if m is None:
|
||||
raise ValueError("Value must be of the form sheetname!A1:E4")
|
||||
sheetname = m.group("quoted") or m.group("notquoted")
|
||||
cells = m.group("cells")
|
||||
boundaries = range_boundaries(cells)
|
||||
return sheetname, boundaries
|
||||
|
||||
|
||||
def quote_sheetname(sheetname):
|
||||
"""
|
||||
Add quotes around sheetnames if they contain spaces.
|
||||
"""
|
||||
if "'" in sheetname:
|
||||
sheetname = sheetname.replace("'", "''")
|
||||
|
||||
sheetname = u"'{0}'".format(sheetname)
|
||||
return sheetname
|
92
.venv/Lib/site-packages/openpyxl/utils/dataframe.py
Normal file
92
.venv/Lib/site-packages/openpyxl/utils/dataframe.py
Normal file
@ -0,0 +1,92 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
from itertools import accumulate
|
||||
import operator
|
||||
|
||||
from openpyxl.compat.product import prod
|
||||
|
||||
|
||||
def dataframe_to_rows(df, index=True, header=True):
|
||||
"""
|
||||
Convert a Pandas dataframe into something suitable for passing into a worksheet.
|
||||
If index is True then the index will be included, starting one row below the header.
|
||||
If header is True then column headers will be included starting one column to the right.
|
||||
Formatting should be done by client code.
|
||||
"""
|
||||
import numpy
|
||||
from pandas import Timestamp
|
||||
blocks = df._data.blocks
|
||||
ncols = sum(b.shape[0] for b in blocks)
|
||||
data = [None] * ncols
|
||||
|
||||
for b in blocks:
|
||||
values = b.values
|
||||
|
||||
if b.dtype.type == numpy.datetime64:
|
||||
values = numpy.array([Timestamp(v) for v in values.ravel()])
|
||||
values = values.reshape(b.shape)
|
||||
|
||||
result = values.tolist()
|
||||
|
||||
for col_loc, col in zip(b.mgr_locs, result):
|
||||
data[col_loc] = col
|
||||
|
||||
if header:
|
||||
if df.columns.nlevels > 1:
|
||||
rows = expand_index(df.columns, header)
|
||||
else:
|
||||
rows = [list(df.columns.values)]
|
||||
for row in rows:
|
||||
n = []
|
||||
for v in row:
|
||||
if isinstance(v, numpy.datetime64):
|
||||
v = Timestamp(v)
|
||||
n.append(v)
|
||||
row = n
|
||||
if index:
|
||||
row = [None]*df.index.nlevels + row
|
||||
yield row
|
||||
|
||||
if index:
|
||||
yield df.index.names
|
||||
|
||||
expanded = ([v] for v in df.index)
|
||||
if df.index.nlevels > 1:
|
||||
expanded = expand_index(df.index)
|
||||
|
||||
for idx, v in enumerate(expanded):
|
||||
row = [data[j][idx] for j in range(ncols)]
|
||||
if index:
|
||||
row = v + row
|
||||
yield row
|
||||
|
||||
|
||||
def expand_index(index, header=False):
|
||||
"""
|
||||
Expand axis or column Multiindex
|
||||
For columns use header = True
|
||||
For axes use header = False (default)
|
||||
"""
|
||||
|
||||
shape = index.levshape
|
||||
depth = prod(shape)
|
||||
row = [None] * index.nlevels
|
||||
lengths = [depth / size for size in accumulate(shape, operator.mul)] # child index lengths
|
||||
columns = [ [] for l in index.names] # avoid copied list gotchas
|
||||
|
||||
for idx, entry in enumerate(index):
|
||||
row = [None] * index.nlevels
|
||||
for level, v in enumerate(entry):
|
||||
length = lengths[level]
|
||||
if idx % length:
|
||||
v = None
|
||||
row[level] = v
|
||||
if header:
|
||||
columns[level].append(v)
|
||||
|
||||
if not header:
|
||||
yield row
|
||||
|
||||
if header:
|
||||
for row in columns:
|
||||
yield row
|
140
.venv/Lib/site-packages/openpyxl/utils/datetime.py
Normal file
140
.venv/Lib/site-packages/openpyxl/utils/datetime.py
Normal file
@ -0,0 +1,140 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
"""Manage Excel date weirdness."""
|
||||
|
||||
# Python stdlib imports
|
||||
import datetime
|
||||
from math import isnan
|
||||
import re
|
||||
|
||||
|
||||
# constants
|
||||
MAC_EPOCH = datetime.datetime(1904, 1, 1)
|
||||
WINDOWS_EPOCH = datetime.datetime(1899, 12, 30)
|
||||
CALENDAR_WINDOWS_1900 = 2415018.5 # Julian date of WINDOWS_EPOCH
|
||||
CALENDAR_MAC_1904 = 2416480.5 # Julian date of MAC_EPOCH
|
||||
CALENDAR_WINDOWS_1900 = WINDOWS_EPOCH
|
||||
CALENDAR_MAC_1904 = MAC_EPOCH
|
||||
SECS_PER_DAY = 86400
|
||||
|
||||
ISO_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
|
||||
ISO_REGEX = re.compile(r'''
|
||||
(?P<date>(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}))?T?
|
||||
(?P<time>(?P<hour>\d{2}):(?P<minute>\d{2})(:(?P<second>\d{2})(?P<microsecond>\.\d{1,3})?)?)?Z?''',
|
||||
re.VERBOSE)
|
||||
ISO_DURATION = re.compile(r'PT((?P<hours>\d+)H)?((?P<minutes>\d+)M)?((?P<seconds>\d+(\.\d{1,3})?)S)?')
|
||||
|
||||
|
||||
def to_ISO8601(dt):
|
||||
"""Convert from a datetime to a timestamp string."""
|
||||
if hasattr(dt, "microsecond") and dt.microsecond:
|
||||
return dt.isoformat(timespec="milliseconds")
|
||||
return dt.isoformat()
|
||||
|
||||
|
||||
def from_ISO8601(formatted_string):
|
||||
"""Convert from a timestamp string to a datetime object. According to
|
||||
18.17.4 in the specification the following ISO 8601 formats are
|
||||
supported.
|
||||
|
||||
Dates B.1.1 and B.2.1
|
||||
Times B.1.2 and B.2.2
|
||||
Datetimes B.1.3 and B.2.3
|
||||
|
||||
There is no concept of timedeltas in the specification, but Excel
|
||||
writes them (in strict OOXML mode), so these are also understood.
|
||||
"""
|
||||
if not formatted_string:
|
||||
return None
|
||||
|
||||
match = ISO_REGEX.match(formatted_string)
|
||||
if match and any(match.groups()):
|
||||
parts = match.groupdict(0)
|
||||
for key in ["year", "month", "day", "hour", "minute", "second"]:
|
||||
if parts[key]:
|
||||
parts[key] = int(parts[key])
|
||||
|
||||
if parts["microsecond"]:
|
||||
parts["microsecond"] = int(float(parts['microsecond']) * 1_000_000)
|
||||
|
||||
if not parts["date"]:
|
||||
dt = datetime.time(parts['hour'], parts['minute'], parts['second'], parts["microsecond"])
|
||||
elif not parts["time"]:
|
||||
dt = datetime.date(parts['year'], parts['month'], parts['day'])
|
||||
else:
|
||||
del parts["time"]
|
||||
del parts["date"]
|
||||
dt = datetime.datetime(**parts)
|
||||
return dt
|
||||
|
||||
match = ISO_DURATION.match(formatted_string)
|
||||
if match and any(match.groups()):
|
||||
parts = match.groupdict(0)
|
||||
for key, val in parts.items():
|
||||
if val:
|
||||
parts[key] = float(val)
|
||||
return datetime.timedelta(**parts)
|
||||
|
||||
raise ValueError("Invalid datetime value {}".format(formatted_string))
|
||||
|
||||
|
||||
def to_excel(dt, epoch=WINDOWS_EPOCH):
|
||||
"""Convert Python datetime to Excel serial"""
|
||||
if isinstance(dt, datetime.time):
|
||||
return time_to_days(dt)
|
||||
if isinstance(dt, datetime.timedelta):
|
||||
return timedelta_to_days(dt)
|
||||
if isnan(dt.year): # Pandas supports Not a Date
|
||||
return
|
||||
|
||||
if not hasattr(dt, "date"):
|
||||
dt = datetime.datetime.combine(dt, datetime.time())
|
||||
|
||||
# rebase on epoch and adjust for < 1900-03-01
|
||||
days = (dt - epoch).days
|
||||
if 0 < days <= 60 and epoch == WINDOWS_EPOCH:
|
||||
days -= 1
|
||||
return days + time_to_days(dt)
|
||||
|
||||
|
||||
def from_excel(value, epoch=WINDOWS_EPOCH, timedelta=False):
|
||||
"""Convert Excel serial to Python datetime"""
|
||||
if value is None:
|
||||
return
|
||||
|
||||
if timedelta:
|
||||
td = datetime.timedelta(days=value)
|
||||
if td.microseconds:
|
||||
# round to millisecond precision
|
||||
td = datetime.timedelta(seconds=td.total_seconds() // 1,
|
||||
microseconds=round(td.microseconds, -3))
|
||||
return td
|
||||
|
||||
day, fraction = divmod(value, 1)
|
||||
diff = datetime.timedelta(milliseconds=round(fraction * SECS_PER_DAY * 1000))
|
||||
if 0 <= value < 1 and diff.days == 0:
|
||||
return days_to_time(diff)
|
||||
if 0 < value < 60 and epoch == WINDOWS_EPOCH:
|
||||
day += 1
|
||||
return epoch + datetime.timedelta(days=day) + diff
|
||||
|
||||
|
||||
def time_to_days(value):
|
||||
"""Convert a time value to fractions of day"""
|
||||
return (
|
||||
(value.hour * 3600)
|
||||
+ (value.minute * 60)
|
||||
+ value.second
|
||||
+ value.microsecond / 10**6
|
||||
) / SECS_PER_DAY
|
||||
|
||||
|
||||
def timedelta_to_days(value):
|
||||
"""Convert a timedelta value to fractions of a day"""
|
||||
return value.total_seconds() / SECS_PER_DAY
|
||||
|
||||
|
||||
def days_to_time(value):
|
||||
mins, seconds = divmod(value.seconds, 60)
|
||||
hours, mins = divmod(mins, 60)
|
||||
return datetime.time(hours, mins, seconds, value.microseconds)
|
43
.venv/Lib/site-packages/openpyxl/utils/escape.py
Normal file
43
.venv/Lib/site-packages/openpyxl/utils/escape.py
Normal file
@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
"""
|
||||
OOXML has non-standard escaping for characters < \031
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def escape(value):
|
||||
r"""
|
||||
Convert ASCII < 31 to OOXML: \n == _x + hex(ord(\n)) + _
|
||||
"""
|
||||
|
||||
CHAR_REGEX = re.compile(r"[\001-\031]")
|
||||
|
||||
def _sub(match):
|
||||
"""
|
||||
Callback to escape chars
|
||||
"""
|
||||
return "_x{:0>4x}_".format(ord(match.group(0)))
|
||||
|
||||
return CHAR_REGEX.sub(_sub, value)
|
||||
|
||||
|
||||
def unescape(value):
|
||||
r"""
|
||||
Convert escaped strings to ASCIII: _x000a_ == \n
|
||||
"""
|
||||
|
||||
|
||||
ESCAPED_REGEX = re.compile("_x([0-9A-Fa-f]{4})_")
|
||||
|
||||
def _sub(match):
|
||||
"""
|
||||
Callback to unescape chars
|
||||
"""
|
||||
return chr(int(match.group(1), 16))
|
||||
|
||||
if "_x" in value:
|
||||
value = ESCAPED_REGEX.sub(_sub, value)
|
||||
|
||||
return value
|
34
.venv/Lib/site-packages/openpyxl/utils/exceptions.py
Normal file
34
.venv/Lib/site-packages/openpyxl/utils/exceptions.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
|
||||
"""Definitions for openpyxl shared exception classes."""
|
||||
|
||||
|
||||
class CellCoordinatesException(Exception):
|
||||
"""Error for converting between numeric and A1-style cell references."""
|
||||
|
||||
|
||||
class IllegalCharacterError(Exception):
|
||||
"""The data submitted which cannot be used directly in Excel files. It
|
||||
must be removed or escaped."""
|
||||
|
||||
|
||||
class NamedRangeException(Exception):
|
||||
"""Error for badly formatted named ranges."""
|
||||
|
||||
|
||||
class SheetTitleException(Exception):
|
||||
"""Error for bad sheet names."""
|
||||
|
||||
|
||||
class InvalidFileException(Exception):
|
||||
"""Error for trying to open a non-ooxml file."""
|
||||
|
||||
|
||||
class ReadOnlyWorkbookException(Exception):
|
||||
"""Error for trying to modify a read-only workbook"""
|
||||
|
||||
|
||||
class WorkbookAlreadySaved(Exception):
|
||||
"""Error when attempting to perform operations on a dump workbook
|
||||
while it has already been dumped once"""
|
9
.venv/Lib/site-packages/openpyxl/utils/formulas.py
Normal file
9
.venv/Lib/site-packages/openpyxl/utils/formulas.py
Normal file
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
"""
|
||||
List of builtin formulae
|
||||
"""
|
||||
|
||||
FORMULAE = ("CUBEKPIMEMBER", "CUBEMEMBER", "CUBEMEMBERPROPERTY", "CUBERANKEDMEMBER", "CUBESET", "CUBESETCOUNT", "CUBEVALUE", "DAVERAGE", "DCOUNT", "DCOUNTA", "DGET", "DMAX", "DMIN", "DPRODUCT", "DSTDEV", "DSTDEVP", "DSUM", "DVAR", "DVARP", "DATE", "DATEDIF", "DATEVALUE", "DAY", "DAYS360", "EDATE", "EOMONTH", "HOUR", "MINUTE", "MONTH", "NETWORKDAYS", "NETWORKDAYS.INTL", "NOW", "SECOND", "TIME", "TIMEVALUE", "TODAY", "WEEKDAY", "WEEKNUM", "WORKDAY ", "WORKDAY.INTL", "YEAR", "YEARFRAC", "BESSELI", "BESSELJ", "BESSELK", "BESSELY", "BIN2DEC", "BIN2HEX", "BIN2OCT", "COMPLEX", "CONVERT", "DEC2BIN", "DEC2HEX", "DEC2OCT", "DELTA", "ERF", "ERFC", "GESTEP", "HEX2BIN", "HEX2DEC", "HEX2OCT", "IMABS", "IMAGINARY", "IMARGUMENT", "IMCONJUGATE", "IMCOS", "IMDIV", "IMEXP", "IMLN", "IMLOG10", "IMLOG2", "IMPOWER", "IMPRODUCT", "IMREAL", "IMSIN", "IMSQRT", "IMSUB", "IMSUM", "OCT2BIN", "OCT2DEC", "OCT2HEX", "ACCRINT", "ACCRINTM", "AMORDEGRC", "AMORLINC", "COUPDAYBS", "COUPDAYS", "COUPDAYSNC", "COUPNCD", "COUPNUM", "COUPPCD", "CUMIPMT", "CUMPRINC", "DB", "DDB", "DISC", "DOLLARDE", "DOLLARFR", "DURATION", "EFFECT", "FV", "FVSCHEDULE", "INTRATE", "IPMT", "IRR", "ISPMT", "MDURATION", "MIRR", "NOMINAL", "NPER", "NPV", "ODDFPRICE", "ODDFYIELD", "ODDLPRICE", "ODDLYIELD", "PMT", "PPMT", "PRICE", "PRICEDISC", "PRICEMAT", "PV", "RATE", "RECEIVED", "SLN", "SYD", "TBILLEQ", "TBILLPRICE", "TBILLYIELD", "VDB", "XIRR", "XNPV", "YIELD", "YIELDDISC", "YIELDMAT", "CELL", "ERROR.TYPE", "INFO", "ISBLANK", "ISERR", "ISERROR", "ISEVEN", "ISLOGICAL", "ISNA", "ISNONTEXT", "ISNUMBER", "ISODD", "ISREF", "ISTEXT", "N", "NA", "TYPE", "AND", "FALSE", "IF", "IFERROR", "NOT", "OR", "TRUE ADDRESS", "AREAS", "CHOOSE", "COLUMN", "COLUMNS", "GETPIVOTDATA", "HLOOKUP", "HYPERLINK", "INDEX", "INDIRECT", "LOOKUP", "MATCH", "OFFSET", "ROW", "ROWS", "RTD", "TRANSPOSE", "VLOOKUP", "ABS", "ACOS", "ACOSH", "ASIN", "ASINH", "ATAN", "ATAN2", "ATANH", "CEILING", "COMBIN", "COS", "COSH", "DEGREES", "ECMA.CEILING", "EVEN", "EXP", "FACT", "FACTDOUBLE", "FLOOR", "GCD", "INT", "ISO.CEILING", "LCM", "LN", "LOG", "LOG10", "MDETERM", "MINVERSE", "MMULT", "MOD", "MROUND", "MULTINOMIAL", "ODD", "PI", "POWER", "PRODUCT", "QUOTIENT", "RADIANS", "RAND", "RANDBETWEEN", "ROMAN", "ROUND", "ROUNDDOWN", "ROUNDUP", "SERIESSUM", "SIGN", "SIN", "SINH", "SQRT", "SQRTPI", "SUBTOTAL", "SUM", "SUMIF", "SUMIFS", "SUMPRODUCT", "SUMSQ", "SUMX2MY2", "SUMX2PY2", "SUMXMY2", "TAN", "TANH", "TRUNC", "AVEDEV", "AVERAGE", "AVERAGEA", "AVERAGEIF", "AVERAGEIFS", "BETADIST", "BETAINV", "BINOMDIST", "CHIDIST", "CHIINV", "CHITEST", "CONFIDENCE", "CORREL", "COUNT", "COUNTA", "COUNTBLANK", "COUNTIF", "COUNTIFS", "COVAR", "CRITBINOM", "DEVSQ", "EXPONDIST", "FDIST", "FINV", "FISHER", "FISHERINV", "FORECAST", "FREQUENCY", "FTEST", "GAMMADIST", "GAMMAINV", "GAMMALN", "GEOMEAN", "GROWTH", "HARMEAN", "HYPGEOMDIST", "INTERCEPT", "KURT", "LARGE", "LINEST", "LOGEST", "LOGINV", "LOGNORMDIST", "MAX", "MAXA", "MEDIAN", "MIN", "MINA", "MODE", "NEGBINOMDIST", "NORMDIST", "NORMINV", "NORMSDIST", "NORMSINV", "PEARSON", "PERCENTILE", "PERCENTRANK", "PERMUT", "POISSON", "PROB", "QUARTILE", "RANK", "RSQ", "SKEW", "SLOPE", "SMALL", "STANDARDIZE", "STDEV STDEVA", "STDEVP", "STDEVPA STEYX", "TDIST", "TINV", "TREND", "TRIMMEAN", "TTEST", "VAR", "VARA", "VARP", "VARPA", "WEIBULL", "ZTEST", "ASC", "BAHTTEXT", "CHAR", "CLEAN", "CODE", "CONCATENATE", "DOLLAR", "EXACT", "FIND", "FINDB", "FIXED", "JIS", "LEFT", "LEFTB", "LEN", "LENB", "LOWER", "MID", "MIDB", "PHONETIC", "PROPER", "REPLACE", "REPLACEB", "REPT", "RIGHT", "RIGHTB", "SEARCH", "SEARCHB", "SUBSTITUTE", "T", "TEXT", "TRIM", "UPPER", "VALUE")
|
||||
|
||||
FORMULAE = frozenset(FORMULAE)
|
49
.venv/Lib/site-packages/openpyxl/utils/indexed_list.py
Normal file
49
.venv/Lib/site-packages/openpyxl/utils/indexed_list.py
Normal file
@ -0,0 +1,49 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
|
||||
class IndexedList(list):
|
||||
"""
|
||||
List with optimised access by value
|
||||
Based on Alex Martelli's recipe
|
||||
|
||||
http://code.activestate.com/recipes/52303-the-auxiliary-dictionary-idiom-for-sequences-with-/
|
||||
"""
|
||||
|
||||
_dict = {}
|
||||
|
||||
def __init__(self, iterable=None):
|
||||
self.clean = True
|
||||
self._dict = {}
|
||||
if iterable is not None:
|
||||
self.clean = False
|
||||
for idx, val in enumerate(iterable):
|
||||
self._dict[val] = idx
|
||||
list.append(self, val)
|
||||
|
||||
def _rebuild_dict(self):
|
||||
self._dict = {}
|
||||
idx = 0
|
||||
for value in self:
|
||||
if value not in self._dict:
|
||||
self._dict[value] = idx
|
||||
idx += 1
|
||||
self.clean = True
|
||||
|
||||
def __contains__(self, value):
|
||||
if not self.clean:
|
||||
self._rebuild_dict()
|
||||
return value in self._dict
|
||||
|
||||
def index(self, value):
|
||||
if value in self:
|
||||
return self._dict[value]
|
||||
raise ValueError
|
||||
|
||||
def append(self, value):
|
||||
if value not in self._dict:
|
||||
self._dict[value] = len(self)
|
||||
list.append(self, value)
|
||||
|
||||
def add(self, value):
|
||||
self.append(value)
|
||||
return self._dict[value]
|
60
.venv/Lib/site-packages/openpyxl/utils/inference.py
Normal file
60
.venv/Lib/site-packages/openpyxl/utils/inference.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
"""
|
||||
Type inference functions
|
||||
"""
|
||||
import datetime
|
||||
import re
|
||||
|
||||
from openpyxl.styles import numbers
|
||||
|
||||
PERCENT_REGEX = re.compile(r'^(?P<number>\-?[0-9]*\.?[0-9]*\s?)\%$')
|
||||
TIME_REGEX = re.compile(r"""
|
||||
^(?: # HH:MM and HH:MM:SS
|
||||
(?P<hour>[0-1]{0,1}[0-9]{2}):
|
||||
(?P<minute>[0-5][0-9]):?
|
||||
(?P<second>[0-5][0-9])?$)
|
||||
|
|
||||
^(?: # MM:SS.
|
||||
([0-5][0-9]):
|
||||
([0-5][0-9])?\.
|
||||
(?P<microsecond>\d{1,6}))
|
||||
""", re.VERBOSE)
|
||||
NUMBER_REGEX = re.compile(r'^-?([\d]|[\d]+\.[\d]*|\.[\d]+|[1-9][\d]+\.?[\d]*)((E|e)[-+]?[\d]+)?$')
|
||||
|
||||
|
||||
def cast_numeric(value):
|
||||
"""Explicity convert a string to a numeric value"""
|
||||
if NUMBER_REGEX.match(value):
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return float(value)
|
||||
|
||||
|
||||
def cast_percentage(value):
|
||||
"""Explicitly convert a string to numeric value and format as a
|
||||
percentage"""
|
||||
match = PERCENT_REGEX.match(value)
|
||||
if match:
|
||||
return float(match.group('number')) / 100
|
||||
|
||||
|
||||
|
||||
def cast_time(value):
|
||||
"""Explicitly convert a string to a number and format as datetime or
|
||||
time"""
|
||||
match = TIME_REGEX.match(value)
|
||||
if match:
|
||||
if match.group("microsecond") is not None:
|
||||
value = value[:12]
|
||||
pattern = "%M:%S.%f"
|
||||
#fmt = numbers.FORMAT_DATE_TIME5
|
||||
elif match.group('second') is None:
|
||||
#fmt = numbers.FORMAT_DATE_TIME3
|
||||
pattern = "%H:%M"
|
||||
else:
|
||||
pattern = "%H:%M:%S"
|
||||
#fmt = numbers.FORMAT_DATE_TIME6
|
||||
value = datetime.datetime.strptime(value, pattern)
|
||||
return value.time()
|
22
.venv/Lib/site-packages/openpyxl/utils/protection.py
Normal file
22
.venv/Lib/site-packages/openpyxl/utils/protection.py
Normal file
@ -0,0 +1,22 @@
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
|
||||
def hash_password(plaintext_password=''):
|
||||
"""
|
||||
Create a password hash from a given string for protecting a worksheet
|
||||
only. This will not work for encrypting a workbook.
|
||||
|
||||
This method is based on the algorithm provided by
|
||||
Daniel Rentz of OpenOffice and the PEAR package
|
||||
Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>.
|
||||
See also http://blogs.msdn.com/b/ericwhite/archive/2008/02/23/the-legacy-hashing-algorithm-in-open-xml.aspx
|
||||
"""
|
||||
password = 0x0000
|
||||
for idx, char in enumerate(plaintext_password, 1):
|
||||
value = ord(char) << idx
|
||||
rotated_bits = value >> 15
|
||||
value &= 0x7fff
|
||||
password ^= (value | rotated_bits)
|
||||
password ^= len(plaintext_password)
|
||||
password ^= 0xCE4B
|
||||
return str(hex(password)).upper()[2:]
|
108
.venv/Lib/site-packages/openpyxl/utils/units.py
Normal file
108
.venv/Lib/site-packages/openpyxl/utils/units.py
Normal file
@ -0,0 +1,108 @@
|
||||
from __future__ import division
|
||||
# Copyright (c) 2010-2022 openpyxl
|
||||
|
||||
import math
|
||||
|
||||
|
||||
#constants
|
||||
|
||||
DEFAULT_ROW_HEIGHT = 15. # Default row height measured in point size.
|
||||
BASE_COL_WIDTH = 8 # in characters
|
||||
DEFAULT_COLUMN_WIDTH = BASE_COL_WIDTH + 5
|
||||
# = baseColumnWidth + {margin padding (2 pixels on each side, totalling 4 pixels)} + {gridline (1pixel)}
|
||||
|
||||
|
||||
DEFAULT_LEFT_MARGIN = 0.7 # in inches, = right margin
|
||||
DEFAULT_TOP_MARGIN = 0.7874 # in inches = bottom margin
|
||||
DEFAULT_HEADER = 0.3 # in inches
|
||||
|
||||
|
||||
# Conversion functions
|
||||
"""
|
||||
From the ECMA Spec (4th Edition part 1)
|
||||
Page setup: "Left Page Margin in inches" p. 1647
|
||||
|
||||
Docs from
|
||||
http://startbigthinksmall.wordpress.com/2010/01/04/points-inches-and-emus-measuring-units-in-office-open-xml/
|
||||
|
||||
See also http://msdn.microsoft.com/en-us/library/dd560821(v=office.12).aspx
|
||||
|
||||
dxa: The main unit in OOXML is a twentieth of a point. Also called twips.
|
||||
pt: point. In Excel there are 72 points to an inch
|
||||
hp: half-points are used to specify font sizes. A font-size of 12pt equals 24 half points
|
||||
pct: Half-points are used to specify font sizes. A font-size of 12pt equals 24 half points
|
||||
|
||||
EMU: English Metric Unit, EMUs are used for coordinates in vector-based
|
||||
drawings and embedded pictures. One inch equates to 914400 EMUs and a
|
||||
centimeter is 360000. For bitmaps the default resolution is 96 dpi (known as
|
||||
PixelsPerInch in Excel). Spec p. 1122
|
||||
|
||||
For radial geometry Excel uses integert units of 1/60000th of a degree.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
def inch_to_dxa(value):
|
||||
"""1 inch = 72 * 20 dxa"""
|
||||
return int(value * 20 * 72)
|
||||
|
||||
def dxa_to_inch(value):
|
||||
return value / 72 / 20
|
||||
|
||||
|
||||
def dxa_to_cm(value):
|
||||
return 2.54 * dxa_to_inch(value)
|
||||
|
||||
def cm_to_dxa(value):
|
||||
emu = cm_to_EMU(value)
|
||||
inch = EMU_to_inch(emu)
|
||||
return inch_to_dxa(inch)
|
||||
|
||||
|
||||
def pixels_to_EMU(value):
|
||||
"""1 pixel = 9525 EMUs"""
|
||||
return int(value * 9525)
|
||||
|
||||
def EMU_to_pixels(value):
|
||||
return round(value / 9525)
|
||||
|
||||
|
||||
def cm_to_EMU(value):
|
||||
"""1 cm = 360000 EMUs"""
|
||||
return int(value * 360000)
|
||||
|
||||
def EMU_to_cm(value):
|
||||
return round(value / 360000, 4)
|
||||
|
||||
|
||||
def inch_to_EMU(value):
|
||||
"""1 inch = 914400 EMUs"""
|
||||
return int(value * 914400)
|
||||
|
||||
def EMU_to_inch(value):
|
||||
return round(value / 914400, 4)
|
||||
|
||||
|
||||
def pixels_to_points(value, dpi=96):
|
||||
"""96 dpi, 72i"""
|
||||
return value * 72 / dpi
|
||||
|
||||
|
||||
def points_to_pixels(value, dpi=96):
|
||||
return int(math.ceil(value * dpi / 72))
|
||||
|
||||
|
||||
def degrees_to_angle(value):
|
||||
"""1 degree = 60000 angles"""
|
||||
return int(round(value * 60000))
|
||||
|
||||
|
||||
def angle_to_degrees(value):
|
||||
return round(value / 60000, 2)
|
||||
|
||||
|
||||
def short_color(color):
|
||||
""" format a color to its short size """
|
||||
if len(color) > 6:
|
||||
return color[2:]
|
||||
return color
|
Reference in New Issue
Block a user