Skip to content

Commit 951a578

Browse files
feat: Add XLSX support to MSD Workbench parser (#1154)
## Summary - Added support for parsing XLSX files in the MSD Workbench parser - Parser now accepts .xlsx files in addition to existing .csv and .txt formats - XLSX files are read from the "Workbench data" sheet using pandas with openpyxl engine ## Changes - Updated `SUPPORTED_EXTENSIONS` in `MSDWorkbenchReader` to include "xlsx" - Added conditional logic to handle XLSX files differently from CSV/TXT files - Created sanitized test XLSX file with fake data (no customer-specific information) - Generated expected JSON output for the test file ## Test plan - [x] Added test case with XLSX file (`test_msd_workbench_xlsx.xlsx`) - [x] All existing tests continue to pass - [x] Linting and type checking pass - [x] Parser correctly reads and processes XLSX files from the "Workbench data" sheet 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.1 <noreply@anthropic.com>
1 parent a89c1f7 commit 951a578

4 files changed

Lines changed: 2264 additions & 2 deletions

File tree

src/allotropy/parsers/msd_workbench/msd_workbench_parser.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MSDWorkbenchParser(VendorParser[Data, Model]):
4141
def create_data(self, named_file_contents: NamedFileContents) -> Data:
4242
if named_file_contents.extension == "txt":
4343
return self._process_methodical_mind(named_file_contents)
44+
# CSV and XLSX files use MSD Workbench format
4445
return self._process_msd_workbench(named_file_contents)
4546

4647
def _process_methodical_mind(self, named_file_contents: NamedFileContents) -> Data:

src/allotropy/parsers/msd_workbench/msd_workbench_reader.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@
66

77

88
class MSDWorkbenchReader:
9-
SUPPORTED_EXTENSIONS = "csv, txt"
9+
SUPPORTED_EXTENSIONS = "csv, txt, xlsx"
1010
plate_data: pd.DataFrame
1111
well_plate_id: str
1212

1313
def __init__(self, named_file_contents: NamedFileContents) -> None:
14-
data = read_csv(named_file_contents.contents)
14+
if named_file_contents.extension == "xlsx":
15+
# Read the Workbench data sheet from Excel file
16+
data = pd.read_excel(
17+
named_file_contents.contents,
18+
sheet_name="Workbench data",
19+
engine="openpyxl",
20+
)
21+
else:
22+
data = read_csv(named_file_contents.contents)
1523
data = data.where(pd.notna(data), None)
1624
data.index = pd.Index(data.index.to_series().ffill())
1725
data.index = data.index.astype(str).str.strip()

0 commit comments

Comments
 (0)