Skip to content

Commit

Permalink
fix(xl_app): Refactor row and column XL-read
Browse files Browse the repository at this point in the history
  • Loading branch information
ed-p-may committed Dec 7, 2022
1 parent 55f7f99 commit c0d9c16
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 49 deletions.
6 changes: 3 additions & 3 deletions PHX/PHPP/phpp_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@ def get_data_worksheet(_xl: xl_app.XLConnection) -> Sheet:
def get_phpp_version(_xl: xl_app.XLConnection,
_search_col: str = "A",
_row_start: int = 1,
_row_end: int = 5) -> Tuple[str, str]:
_row_end: int = 10) -> Tuple[str, str]:
"""Find the PHPP Version and Language of the active xl-file.
Arguments:
----------
* _xl (xl_app.XLConnection):
* _search_col (str)
* _row_start (int) default=1
* _row_end (int) default=5
* _row_end (int) default=10
Returns:
--------
Expand Down Expand Up @@ -74,7 +74,7 @@ def get_phpp_version(_xl: xl_app.XLConnection,

# -- Pull the search row data from the Active XL Instance
data = _xl.get_single_row_data(data_worksheet.name, data_row)
data = [_ for _ in data if _ is not None]
data = [_ for _ in data if _ is not None and _ is not ""]

# -- Find the right Versions number
version = str(data[1]).upper().strip().replace(" ", "").replace(".", "_")
Expand Down
45 changes: 27 additions & 18 deletions PHX/PHPP/sheet_io/io_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def find_section_header_row(self, _row_start: int = 1, _row_end: int = 100) -> i
_row_end=_row_end,
)

for i, val in enumerate(xl_data):
for i, val in enumerate(xl_data, start=1):
if val == self.shape.surface_rows.locator_string_header:
return i

Expand All @@ -102,7 +102,7 @@ def find_section_first_entry_row(self) -> int:

for i, val in enumerate(xl_data, start=self.section_header_row):
try:
val = str(int(val)) # Value comes in as "1.0" from Excel?
val = str(int(val)) # type: ignore - Value comes in as "1.0" from Excel?
except:
continue

Expand Down Expand Up @@ -142,8 +142,8 @@ def get_surface_phpp_id_by_name(self, _name: str, _use_cache: bool = False) -> s
self.shape.name,
f"{col_offset(str(self.shape.surface_rows.inputs.description.column), -1)}{row}",
)
print(f"Getting PHPP Surface id for {_name}")
name = f"{int(prefix)}-{_name}"
self.xl.output(f"Getting PHPP Surface id for {_name}")
name = f"{int(str(prefix))}-{_name}"

# -- Save in cache
self.surface_cache[_name] = name
Expand All @@ -155,8 +155,20 @@ class ThermalBridges:
def __init__(self, _xl: xl_app.XLConnection, _shape: shape_model.Areas):
self.xl = _xl
self.shape = _shape
self.section_header_row: Optional[int] = None
self.section_first_entry_row: Optional[int] = None
self._section_header_row: Optional[int] = None
self._section_first_entry_row: Optional[int] = None

@property
def section_header_row(self) -> int:
if not self._section_header_row:
self._section_header_row = self.find_section_header_row()
return self._section_header_row

@property
def section_first_entry_row(self) -> int:
if not self._section_first_entry_row:
self._section_first_entry_row = self.find_section_first_entry_row()
return self._section_first_entry_row

def find_section_header_row(self, _row_start: int = 100, _row_end: int = 500) -> int:
"""Return the row number of the 'Thermal Bridge input' section header."""
Expand Down Expand Up @@ -189,9 +201,6 @@ def find_section_header_row(self, _row_start: int = 100, _row_end: int = 500) ->
def find_section_first_entry_row(self) -> int:
"""Return the row number of the very first user-input entry row in the 'Thermal Bridge input' section."""

if not self.section_header_row:
self.section_header_row = self.find_section_header_row()

xl_data = self.xl.get_single_column_data(
_sheet_name=self.shape.name,
_col=self.shape.thermal_bridge_rows.locator_col_entry,
Expand All @@ -201,7 +210,7 @@ def find_section_first_entry_row(self) -> int:

for i, val in enumerate(xl_data, start=self.section_header_row):
try:
val = str(int(val)) # Value comes in as "1.0" from Excel?
val = str(int(val)) # type: ignore - Value comes in as "1.0" from Excel?
except:
continue

Expand All @@ -225,20 +234,20 @@ def __init__(self, _xl: xl_app.XLConnection, _shape: shape_model.Areas):
def write_thermal_bridges(
self, _tbs: List[areas_thermal_bridges.ThermalBridgeRow]
) -> None:
if not self.thermal_bridges.section_first_entry_row:
self.thermal_bridges.section_first_entry_row = (
self.thermal_bridges.find_section_first_entry_row()
)
# if not self.thermal_bridges.section_first_entry_row:
# self.thermal_bridges.section_first_entry_row = (
# self.thermal_bridges.find_section_first_entry_row()
# )

for i, tb in enumerate(_tbs, start=self.thermal_bridges.section_first_entry_row):
for item in tb.create_xl_items(self.shape.name, _row_num=i):
self.xl.write_xl_item(item)

def write_surfaces(self, _surfaces: List[areas_surface.SurfaceRow]) -> None:
if not self.surfaces.section_first_entry_row:
self.surfaces.section_first_entry_row = (
self.surfaces.find_section_first_entry_row()
)
# if not self.surfaces.section_first_entry_row:
# self.surfaces.section_first_entry_row = (
# self.surfaces.find_section_first_entry_row()
# )

for i, surface in enumerate(
_surfaces, start=self.surfaces.section_first_entry_row
Expand Down
90 changes: 70 additions & 20 deletions PHX/xl/xl_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def __init__(self, _value, _range, _worksheet, _e):


# -----------------------------------------------------------------------------


def silent_print(_input: Any) -> None:
"""Default 'output' for XLConnection."""
return
Expand Down Expand Up @@ -198,49 +200,98 @@ def create_new_worksheet(self, _sheet_name: str) -> None:

self.get_sheet_by_name(_sheet_name).clear()

def get_last_used_row_num_in_column(self, _sheet_name: str, _col: str) -> int:
"""Return the row number of the last cell in a column with a value in it.
Arguments:
----------
* _sheet_name (str): The name of the Worksheet to read from.
* _col (str): The Alpha character of the column to read.
Returns:
--------
* (int): The number of the last row in the column with a value.
"""
sheet = self.get_sheet_by_name(_sheet_name)
sheet.activate()
col_range = sheet.range(f"{_col}:{_col}")
col_last_cell_range = sheet.range(col_range.last_cell.address)
group_last_cell_range = col_last_cell_range.end("up") # same as 'Ctrl-Up'
return group_last_cell_range.row

def get_single_column_data(
self,
_sheet_name: str,
_col: str,
_row_start: int = 1,
_row_end: int = 100,
_row_start: Optional[int] = None,
_row_end: Optional[int] = None,
) -> List[xl_data.xl_range_value]:
"""Return a list with the values read from a single column of the excel document.
Arguments:
----------
* _sheet_name: (str) The Excel Worksheet to read from.
* _col: (str) The Column letter to read.
* _row_start: (int) default=1
* _row_end: (int) default=100
* _row_start: (Optional[int]) default=None
* _row_end: (Optional[int]) default=None
Returns:
--------
(List[xl_range_value]): The data from Excel worksheet, as a list.
"""

return (
self.get_sheet_by_name(_sheet_name)
.range(f"{_col}{_row_start}:{_col}{_row_end}")
.value
)
if not _row_start or not _row_end:
_row_start = 1
_row_end = self.get_last_used_row_num_in_column(_sheet_name, _col)

address = f"{_col}{_row_start}:{_col}{_row_end}"
self.output(f"Reading: '{address}' data on sheet: '{_sheet_name}'")

sheet = self.get_sheet_by_name(_sheet_name)
sheet.activate()
col_range = sheet.range(f"{address}")
return col_range.value # type: ignore

def get_last_used_column_in_row(self, _sheet_name: str, _row: int) -> str:
"""Return the column letter of the last cell in a column with a value in it.
Arguments:
----------
* _sheet_name (str): The name of the Worksheet to read from.
* _col (str): The Alpha character of the column to read.
Returns:
--------
* (str): The Letter of the last column in the row with a value.
"""
sheet = self.get_sheet_by_name(_sheet_name)
sheet.activate()
row_range = sheet.range(f"{_row}:{_row}")
row_last_cell_range = sheet.range(row_range.last_cell.address)
group_last_cell_range = row_last_cell_range.end("left") # same as 'Ctrl-Left'
return xl_data.xl_chr(xl_data.xl_ord("A") + group_last_cell_range.column - 1)

def get_single_row_data(
self, _sheet_name: str, _row_number: int
) -> List[xl_data.xl_range_value]:
"""
) -> List[xl_data.xl_range_single_value]:
"""Return all the data from a single Row in the Excel Workbook.
Arguments:
----------
* _sheet_name (str): The name of the sheet to read
* _row_number (int): The row to read
* _row_number (int): The row number to read
Returns:
--------
* (List[xl_data.xl_range_value]) The data read from XL.
* (List[xl_data.xl_range_single_value]) A List of the data read from XL.
"""

sht = self.get_sheet_by_name(_sheet_name)
return sht.range((_row_number, 1), (_row_number, 500)).value
self.output(f"Reading: Row-{_row_number} on sheet: '{_sheet_name}'")

sheet = self.get_sheet_by_name(_sheet_name)
sheet.activate()
last_col_letter = self.get_last_used_column_in_row(_sheet_name, _row_number)
row_range = sheet.range(f"A{_row_number}:{last_col_letter}{_row_number}")
return row_range.value # type: ignore

def get_multiple_column_data(
self,
Expand All @@ -249,8 +300,8 @@ def get_multiple_column_data(
_col_end: str,
_row_start: int = 1,
_row_end: int = 100,
) -> List[List[xl_data.xl_range_value]]:
"""Return a list with the values read from a specified block of the xl document.
) -> xl_data.xl_range_value:
"""Return a list of lists with the values read from a specified block of the xl document.
Arguments:
----------
Expand All @@ -268,8 +319,7 @@ def get_multiple_column_data(
if _col_start == _col_end:
raise ReadMultipleColumnsError(_col_start, _col_end)

# -- Use xl.Range() instead of ord() since ord('KL') and similar will fail
# rng = xw.Range(f"{_col_end}1:{_col_start}1")
# -- Use xl.Range() instead of ord() since ord('KL') will fail
rng: xl_Range_Protocol = self.xl.Range(f"{_col_end}1:{_col_start}1")
_ndim = len(rng.columns)

Expand Down Expand Up @@ -306,7 +356,7 @@ def write_xl_item(self, _xl_item: xl_data.XlItem) -> None:
)
xl_sheet = self.get_sheet_by_name(_xl_item.sheet_name)
xl_range = xl_sheet.range(_xl_item.xl_range)
xl_range.value = _xl_item.write_value
xl_range.value = _xl_item.write_value # type: ignore

if _xl_item.font_color or _xl_item.range_color:
xl_range.color = _xl_item.range_color
Expand Down
9 changes: 8 additions & 1 deletion PHX/xl/xl_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
from ph_units import converter

xl_writable = Optional[Union[str, float, int, List, Tuple]]
xl_range_value = Optional[Union[str, float, int]]
xl_range_single_value = Union[str, float, int, None]
xl_range_list1D_value = Union[List[str], List[float], List[int], List[None]]
xl_range_list2D_value = Union[
List[List[str]], List[List[float]], List[List[int]], List[List[None]]
]
xl_range_value = Union[
xl_range_single_value, xl_range_list1D_value, xl_range_list2D_value
]


def xl_ord(_col: str) -> int:
Expand Down
18 changes: 17 additions & 1 deletion PHX/xl/xl_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,23 @@ def __len__(self) -> int:
...


class xl_CellRange_Protocol:
def __init__(self):
self.address: str


class xl_Range_Protocol:
def __init__(self):
self.value: xl_data.xl_writable
self.value: xl_data.xl_range_value
self.color: Optional[Tuple[int, ...]]
self.font: xl_Range_Font = xl_Range_Font()
self.columns: xl_RangeColumns_Protocol = xl_RangeColumns_Protocol()
self.last_cell: xl_CellRange_Protocol
self.row: int
self.column: int

def end(self, *args, **kwargs) -> "xl_Range_Protocol":
return xl_Range_Protocol()

def options(self, ndim: int) -> "xl_Range_Protocol":
return xl_Range_Protocol()
Expand All @@ -48,6 +59,8 @@ def offset(self, row_offset: int = 0, column_offset: int = 0) -> "xl_Range_Proto
class xl_API_Protocol:
def __init__(self, sheet):
self.sheet: "xl_Sheet_Protocol" = sheet
self.rows: Dict
self.Rows: Dict

def unprotect(self):
self.sheet.protected = False
Expand Down Expand Up @@ -80,6 +93,9 @@ def clear_formats(self) -> None:
def clear(self) -> None:
return None

def activate(self) -> None:
...


class xl_Sheets_Protocol:
def __init__(self):
Expand Down
12 changes: 6 additions & 6 deletions _testing_to_PHPP.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
phpp_conn = phpp_app.PHPPConnection(xl, phpp_shape)

try:
xl.output(
f"[bold green]> connected to excel doc: {phpp_conn.xl.wb.name}[/bold green]"
)
clr = "bold green"
msg = f"[{clr}]> connected to excel doc: {phpp_conn.xl.wb.name}[/{clr}]"
xl.output(msg)
except xl_app.NoActiveExcelRunningError as e:
raise e

Expand All @@ -56,10 +56,10 @@
# phpp_conn.write_certification_config(phx_project)
# phpp_conn.write_climate_data(phx_project)
# phpp_conn.write_project_constructions(phx_project)
# phpp_conn.write_project_tfa(phx_project)
# phpp_conn.write_project_opaque_surfaces(phx_project)
phpp_conn.write_project_tfa(phx_project)
phpp_conn.write_project_opaque_surfaces(phx_project)
# phpp_conn.write_project_thermal_bridges(phx_project)
phpp_conn.write_project_window_components(phx_project)
# phpp_conn.write_project_window_components(phx_project)
# phpp_conn.write_project_window_surfaces(phx_project)
# phpp_conn.write_project_window_shading(phx_project)
# phpp_conn.write_project_ventilation_components(phx_project)
Expand Down

0 comments on commit c0d9c16

Please sign in to comment.