about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py')
-rw-r--r--.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py b/.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py
new file mode 100644
index 00000000..f56a4887
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/openpyxl/utils/dataframe.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2010-2024 openpyxl
+
+from itertools import accumulate
+import operator
+import numpy
+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.
+    """
+    from pandas import Timestamp
+
+    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)
+
+    # Using the expanded index is preferable to df.itertuples(index=True) so that we have 'None' inserted where applicable
+    for (df_index, row) in zip(expanded, df.itertuples(index=False)):
+        row = list(row)
+        if index:
+            row = df_index + 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)
+    """
+
+    # For each element of the index, zip the members with the previous row
+    # If the 2 elements of the zipped list do not match, we can insert the new value into the row
+    # or if an earlier member was different, all later members should be added to the row
+    values = list(index.values)
+    previous_value = [None] * len(values[0])
+    result = []
+
+    for value in values:
+        row = [None] * len(value)
+
+        # Once there's a difference in member of an index with the prior index, we need to store all subsequent members in the row
+        prior_change = False
+        for idx, (current_index_member, previous_index_member) in enumerate(zip(value, previous_value)):
+
+            if current_index_member != previous_index_member or prior_change:
+                row[idx] = current_index_member
+                prior_change = True
+
+        previous_value = value
+
+        # If this is for a row index, we're already returning a row so just yield
+        if not header:
+            yield row
+        else:
+            result.append(row)
+
+    # If it's for a header, we need to transpose to get it in row order
+    # Example: result = [['A', 'A'], [None, 'B']] -> [['A', None], ['A', 'B']]
+    if header:
+        result = numpy.array(result).transpose().tolist()
+        for row in result:
+            yield row