@@ -1104,9 +1104,20 @@ def read_xlsx(
1104
1104
1105
1105
See Also
1106
1106
--------
1107
- [DuckDB's `excel` extension docs](https://duckdb.org/docs/stable/extensions/excel.html)
1107
+ [DuckDB's `excel` extension docs for reading](https://duckdb.org/docs/stable/extensions/excel.html#reading-xlsx-files)
1108
+
1109
+ Examples
1110
+ --------
1111
+ >>> import os
1112
+ >>> import ibis
1113
+ >>> t = ibis.memtable({"a": [1, 2, 3], "b": ["a", "b", "c"]})
1114
+ >>> con = ibis.duckdb.connect()
1115
+ >>> con.to_xlsx(t, "/tmp/test.xlsx", header=True)
1116
+ >>> assert os.path.exists("/tmp/test.xlsx")
1117
+ >>> t = con.read_xlsx("/tmp/test.xlsx")
1118
+ >>> t.columns
1119
+ ('a', 'b')
1108
1120
"""
1109
- path = str (path )
1110
1121
table_name = util .gen_name ("read_xlsx" )
1111
1122
1112
1123
if sheet :
@@ -1119,13 +1130,70 @@ def read_xlsx(
1119
1130
sg .to_identifier (key ).eq (sge .convert (val )) for key , val in kwargs .items ()
1120
1131
]
1121
1132
1122
- self ._load_extensions ([ "excel" ] )
1133
+ self .load_extension ( "excel" )
1123
1134
self ._create_temp_view (
1124
1135
table_name ,
1125
- sg .select (STAR ).from_ (self .compiler .f .read_xlsx (path , * options )),
1136
+ sg .select (STAR ).from_ (self .compiler .f .read_xlsx (str ( path ) , * options )),
1126
1137
)
1127
1138
return self .table (table_name )
1128
1139
1140
+ def to_xlsx (
1141
+ self ,
1142
+ expr : ir .Table ,
1143
+ / ,
1144
+ path : str | Path ,
1145
+ * ,
1146
+ sheet : str = "Sheet1" ,
1147
+ header : bool = False ,
1148
+ params : Mapping [ir .Scalar , Any ] | None = None ,
1149
+ ** kwargs : Any ,
1150
+ ):
1151
+ """Write a table to an Excel file.
1152
+
1153
+ Parameters
1154
+ ----------
1155
+ expr
1156
+ Ibis table expression to write to an excel file.
1157
+ path
1158
+ Excel output path.
1159
+ sheet
1160
+ The name of the sheet to write to, eg 'Sheet3'.
1161
+ header
1162
+ Whether to include the column names as the first row.
1163
+ params
1164
+ Additional Ibis expression parameters to pass to the backend's
1165
+ write function.
1166
+ kwargs
1167
+ Additional arguments passed to the backend's write function.
1168
+
1169
+ Notes
1170
+ -----
1171
+ Requires DuckDB >= 1.2.0.
1172
+
1173
+ See Also
1174
+ --------
1175
+ [DuckDB's `excel` extension docs for writing](https://duckdb.org/docs/stable/extensions/excel.html#writing-xlsx-files)
1176
+
1177
+ Examples
1178
+ --------
1179
+ >>> import os
1180
+ >>> import ibis
1181
+ >>> t = ibis.memtable({"a": [1, 2, 3], "b": ["a", "b", "c"]})
1182
+ >>> con = ibis.duckdb.connect()
1183
+ >>> con.to_xlsx(t, "/tmp/test.xlsx")
1184
+ >>> os.path.exists("/tmp/test.xlsx")
1185
+ True
1186
+ """
1187
+ self ._run_pre_execute_hooks (expr )
1188
+ query = self .compile (expr , params = params )
1189
+ kwargs ["sheet" ] = sheet
1190
+ kwargs ["header" ] = header
1191
+ args = ["FORMAT 'xlsx'" ]
1192
+ args .extend (f"{ k .upper ()} { v !r} " for k , v in kwargs .items ())
1193
+ copy_cmd = f"COPY ({ query } ) TO { str (path )!r} ({ ', ' .join (args )} )"
1194
+ self .load_extension ("excel" )
1195
+ self .con .execute (copy_cmd ).fetchall ()
1196
+
1129
1197
def attach (
1130
1198
self , path : str | Path , name : str | None = None , read_only : bool = False
1131
1199
) -> None :
0 commit comments