PHP Classes

File: extension/easy_excel.go

Recommend this page to a friend!
  Packages of Roni   Easy-Excel   extension/easy_excel.go   Download  
File: extension/easy_excel.go
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Easy-Excel
Export and read XLSX files with a PHP Go extension
Author: By
Last change:
Date: 7 days ago
Size: 26,003 bytes
 

Contents

Class file image Download
// easy_excel.go is the FrankenPHP bridge: the flat, handle-first ABI exposed // to PHP (PLAN.md §4). It contains no spreadsheet logic ? it marshals // arguments, dispatches to core, and encodes results. // // Error convention (the generator cannot throw PHP exceptions from Go): // - mutating functions return ?string ? null on success, message on error; // - value-returning functions return array{0: mixed, 1: ?string}; // - messages are prefixed "OVERLOADED:", "DENIED:" or "BADHANDLE:" so the // PHP shim can raise typed exceptions (see EasyExcel\Native::raise()). // // Build (Docker is the supported path, see Dockerfile / README): // // GEN_STUB_SCRIPT=php-src/build/gen_stub.php frankenphp extension-init easy_excel.go // # generates easy_excel.c/.h, _arginfo.h, _generated.go in-place // CGO_ENABLED=1 CGO_CFLAGS=$(php-config --includes) \ // CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)" \ // xcaddy build --output frankenphp \ // --with github.com/dunglas/frankenphp/caddy \ // --with github.com/xiidea/easy-excel/extension=$PWD // // Note: the generator requires each Go parameter declared separately // (no grouped `a, b int64`), and gofmt must not touch this file ? it // mangles //export_php: directives. package easy_excel // #include <Zend/zend_types.h> import "C" import ( "errors" "fmt" "time" "unsafe" "github.com/dunglas/frankenphp" "github.com/xiidea/easy-excel/extension/compat" "github.com/xiidea/easy-excel/extension/core" "github.com/xiidea/easy-excel/extension/exio" "github.com/xiidea/easy-excel/extension/limits" "github.com/xiidea/easy-excel/extension/registry" ) // version is stamped at release build time via -ldflags -X (see the build // stage in Dockerfile / publish.yml), so easy_excel_version() reports the // same vX.Y.Z tag the php-polyfill package is released under. A `var` (not // `const`) is required for -X to reach it. The literal here is only what a // host/dev build without VERSION set reports. var version = "0.0.0-dev" // Process-wide state: one gate, one policy, one handle table // (PLAN.md §7). The 10-minute idle TTL is the leak backstop for PHP code // that never reaches the shim's shutdown handler. var ( gate = limits.NewGate(limits.FromEnv()) policy = mustPolicy() env = &core.Env{Gate: gate, Policy: policy} handles = registry.New(10 * time.Minute) ) func mustPolicy() *exio.Policy { p, err := exio.FromEnv() if err != nil { panic(err) } return p } // --- result encoding --------------------------------------------------------- func errString(err error) string { switch { case errors.Is(err, limits.ErrOverloaded): return "OVERLOADED: " + err.Error() case errors.Is(err, exio.ErrDenied): return "DENIED: " + err.Error() case errors.Is(err, registry.ErrNotFound): return "BADHANDLE: " + err.Error() default: return err.Error() } } // errOnly encodes the ?string convention for mutating functions. func errOnly(err error) unsafe.Pointer { if err == nil { return nil } return frankenphp.PHPString(errString(err), false) } // pair encodes the array{0: mixed, 1: ?string} convention. func pair(value any, err error) unsafe.Pointer { if err != nil { return frankenphp.PHPPackedArray([]any{nil, errString(err)}) } return frankenphp.PHPPackedArray([]any{value, nil}) } func workbook(handle int64) (*core.Workbook, error) { v, err := handles.Get(handle) if err != nil { return nil, err } wb, ok := v.(*core.Workbook) if !ok { return nil, registry.ErrNotFound } return wb, nil } func goStr(s *C.zend_string) string { return frankenphp.GoString(unsafe.Pointer(s)) } // --- lifecycle ---------------------------------------------------------------- //export_php:function easy_excel_version(): string func easy_excel_version() unsafe.Pointer { return frankenphp.PHPString(version, false) } //export_php:function easy_excel_new(): array func easy_excel_new() unsafe.Pointer { wb, err := core.New(env) if err != nil { return pair(nil, err) } return pair(handles.Put(wb), nil) } //export_php:function easy_excel_open(string $path, string $password): array func easy_excel_open(path *C.zend_string, password *C.zend_string) unsafe.Pointer { wb, err := core.Open(goStr(path), goStr(password), env) if err != nil { return pair(nil, err) } return pair(handles.Put(wb), nil) } //export_php:function easy_excel_close(int $handle): ?string func easy_excel_close(handle int64) unsafe.Pointer { v, err := handles.Remove(handle) if err != nil { // closing a stale handle is a no-op, not an error: destructor + // shutdown handler + TTL janitor may race benignly return nil } if wb, ok := v.(*core.Workbook); ok { return errOnly(wb.Close()) } return nil } // --- sheet management ---------------------------------------------------------- //export_php:function easy_excel_add_sheet(int $handle, string $name): array func easy_excel_add_sheet(handle int64, name *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } idx, err := wb.AddSheet(goStr(name)) return pair(int64(idx), err) } //export_php:function easy_excel_delete_sheet(int $handle, string $name): ?string func easy_excel_delete_sheet(handle int64, name *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.DeleteSheet(goStr(name))) } //export_php:function easy_excel_rename_sheet(int $handle, string $old, string $new): ?string func easy_excel_rename_sheet(handle int64, oldName *C.zend_string, newName *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.RenameSheet(goStr(oldName), goStr(newName))) } //export_php:function easy_excel_sheets(int $handle): array func easy_excel_sheets(handle int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } names := wb.Sheets() list := make([]any, len(names)) for i, n := range names { list[i] = n } return pair(list, nil) } //export_php:function easy_excel_set_active_sheet(int $handle, int $index): ?string func easy_excel_set_active_sheet(handle int64, index int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetActiveSheet(int(index))) } //export_php:function easy_excel_active_sheet(int $handle): array func easy_excel_active_sheet(handle int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } pos, name := wb.ActiveSheet() return pair([]any{int64(pos), name}, nil) } // --- write path ----------------------------------------------------------------- //export_php:function easy_excel_write_rows(int $handle, string $sheet, int $startRow, int $startCol, array $rows): ?string func easy_excel_write_rows(handle int64, sheet *C.zend_string, startRow int64, startCol int64, rows *C.zend_array) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } rawRows, err := frankenphp.GoPackedArray[any](unsafe.Pointer(rows)) if err != nil { return errOnly(fmt.Errorf("easy-excel: rows must be a packed array: %w", err)) } batch := make([][]compat.Cell, len(rawRows)) for i, rr := range rawRows { cells, ok := rr.([]any) if !ok { return errOnly(fmt.Errorf("easy-excel: row %d is not a packed array (got %T)", i, rr)) } row := make([]compat.Cell, len(cells)) for j, cv := range cells { c, err := compat.Decode(cv) if err != nil { return errOnly(fmt.Errorf("row %d col %d: %w", i, j, err)) } row[j] = c } batch[i] = row } return errOnly(wb.WriteRows(goStr(sheet), int(startRow), int(startCol), batch)) } //export_php:function easy_excel_set_cell(int $handle, string $sheet, string $cell, array $value): ?string func easy_excel_set_cell(handle int64, sheet *C.zend_string, cell *C.zend_string, value *C.zend_array) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } // value is [scalar] for auto-binding or [marker, scalar] for explicit parts, err := frankenphp.GoPackedArray[any](unsafe.Pointer(value)) if err != nil { return errOnly(err) } var c compat.Cell switch len(parts) { case 1: c, err = compat.Decode(parts[0]) case 2: c, err = compat.Decode(parts) default: err = fmt.Errorf("easy-excel: cell value must be [value] or [marker, value]") } if err != nil { return errOnly(err) } return errOnly(wb.SetCell(goStr(sheet), goStr(cell), c)) } // --- read path -------------------------------------------------------------------- //export_php:function easy_excel_get_cell(int $handle, string $sheet, string $cell, int $mode): array func easy_excel_get_cell(handle int64, sheet *C.zend_string, cell *C.zend_string, mode int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } v, err := wb.GetCell(goStr(sheet), goStr(cell), core.GetMode(mode)) return pair(v, err) } //export_php:function easy_excel_read_rows(int $handle, string $sheet, int $startRow, int $maxRows, bool $raw, bool $calc): array func easy_excel_read_rows(handle int64, sheet *C.zend_string, startRow int64, maxRows int64, raw bool, calc bool) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } rows, more, err := wb.ReadRows(goStr(sheet), int(startRow), int(maxRows), raw, calc) if err != nil { return pair(nil, err) } out := make([]any, len(rows)) for i, r := range rows { cols := make([]any, len(r)) for j, c := range r { cols[j] = c } out[i] = cols } return pair([]any{out, more}, nil) } //export_php:function easy_excel_dimensions(int $handle, string $sheet): array func easy_excel_dimensions(handle int64, sheet *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } maxRow, maxCol, err := wb.Dimensions(goStr(sheet)) return pair([]any{int64(maxRow), int64(maxCol)}, err) } // --- styling / structure ------------------------------------------------------------- //export_php:function easy_excel_set_number_format(int $handle, string $sheet, string $range, string $code): ?string func easy_excel_set_number_format(handle int64, sheet *C.zend_string, ref *C.zend_string, code *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetNumberFormat(goStr(sheet), goStr(ref), goStr(code))) } //export_php:function easy_excel_merge_cells(int $handle, string $sheet, string $range): ?string func easy_excel_merge_cells(handle int64, sheet *C.zend_string, ref *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.MergeCells(goStr(sheet), goStr(ref))) } //export_php:function easy_excel_apply_style(int $handle, string $sheet, string $range, string $styleJson): ?string func easy_excel_apply_style(handle int64, sheet *C.zend_string, ref *C.zend_string, styleJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.ApplyStyle(goStr(sheet), goStr(ref), goStr(styleJson))) } //export_php:function easy_excel_set_col_width(int $handle, string $sheet, int $startCol, int $endCol, float $width): ?string func easy_excel_set_col_width(handle int64, sheet *C.zend_string, startCol int64, endCol int64, width float64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetColWidth(goStr(sheet), int(startCol), int(endCol), width)) } //export_php:function easy_excel_set_col_autosize(int $handle, string $sheet, int $startCol, int $endCol): ?string func easy_excel_set_col_autosize(handle int64, sheet *C.zend_string, startCol int64, endCol int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetColAutoSize(goStr(sheet), int(startCol), int(endCol))) } //export_php:function easy_excel_set_row_height(int $handle, string $sheet, int $row, float $height): ?string func easy_excel_set_row_height(handle int64, sheet *C.zend_string, row int64, height float64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetRowHeight(goStr(sheet), int(row), height)) } //export_php:function easy_excel_set_default_row_height(int $handle, string $sheet, float $height): ?string func easy_excel_set_default_row_height(handle int64, sheet *C.zend_string, height float64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDefaultRowHeight(goStr(sheet), height)) } //export_php:function easy_excel_set_default_col_width(int $handle, string $sheet, float $width): ?string func easy_excel_set_default_col_width(handle int64, sheet *C.zend_string, width float64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDefaultColWidth(goStr(sheet), width)) } //export_php:function easy_excel_freeze_panes(int $handle, string $sheet, string $topLeftCell): ?string func easy_excel_freeze_panes(handle int64, sheet *C.zend_string, topLeftCell *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.FreezePanes(goStr(sheet), goStr(topLeftCell))) } //export_php:function easy_excel_auto_filter(int $handle, string $sheet, string $range): ?string func easy_excel_auto_filter(handle int64, sheet *C.zend_string, ref *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.AutoFilter(goStr(sheet), goStr(ref))) } //export_php:function easy_excel_set_hyperlink(int $handle, string $sheet, string $cell, string $url, string $tooltip): ?string func easy_excel_set_hyperlink(handle int64, sheet *C.zend_string, cell *C.zend_string, url *C.zend_string, tooltip *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetHyperlink(goStr(sheet), goStr(cell), goStr(url), goStr(tooltip))) } //export_php:function easy_excel_set_comment(int $handle, string $sheet, string $cell, string $author, string $text): ?string func easy_excel_set_comment(handle int64, sheet *C.zend_string, cell *C.zend_string, author *C.zend_string, text *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetComment(goStr(sheet), goStr(cell), goStr(author), goStr(text))) } //export_php:function easy_excel_defined_name(int $handle, string $name, string $refersTo, string $scopeSheet): ?string func easy_excel_defined_name(handle int64, name *C.zend_string, refersTo *C.zend_string, scopeSheet *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDefinedName(goStr(name), goStr(refersTo), goStr(scopeSheet))) } //export_php:function easy_excel_page_setup(int $handle, string $sheet, string $orientation, int $paperSize, int $fitToWidth, int $fitToHeight): ?string func easy_excel_page_setup(handle int64, sheet *C.zend_string, orientation *C.zend_string, paperSize int64, fitToWidth int64, fitToHeight int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetPageSetup(goStr(sheet), goStr(orientation), int(paperSize), int(fitToWidth), int(fitToHeight))) } //export_php:function easy_excel_set_validation(int $handle, string $sheet, string $range, string $validationJson): ?string func easy_excel_set_validation(handle int64, sheet *C.zend_string, ref *C.zend_string, validationJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDataValidation(goStr(sheet), goStr(ref), goStr(validationJson))) } //export_php:function easy_excel_set_conditional(int $handle, string $sheet, string $range, string $rulesJson): ?string func easy_excel_set_conditional(handle int64, sheet *C.zend_string, ref *C.zend_string, rulesJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetConditionalFormat(goStr(sheet), goStr(ref), goStr(rulesJson))) } //export_php:function easy_excel_add_image(int $handle, string $sheet, string $cell, string $imageJson): ?string func easy_excel_add_image(handle int64, sheet *C.zend_string, cell *C.zend_string, imageJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.AddImage(goStr(sheet), goStr(cell), goStr(imageJson))) } //export_php:function easy_excel_protect_sheet(int $handle, string $sheet, string $protectionJson): ?string func easy_excel_protect_sheet(handle int64, sheet *C.zend_string, protectionJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.ProtectSheet(goStr(sheet), goStr(protectionJson))) } //export_php:function easy_excel_add_chart(int $handle, string $sheet, string $cell, string $chartJson): ?string func easy_excel_add_chart(handle int64, sheet *C.zend_string, cell *C.zend_string, chartJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.AddChart(goStr(sheet), goStr(cell), goStr(chartJson))) } // --- save ------------------------------------------------------------------------- //export_php:function easy_excel_save_xlsx(int $handle, string $path, string $password): ?string func easy_excel_save_xlsx(handle int64, path *C.zend_string, password *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SaveXlsx(goStr(path), goStr(password))) } //export_php:function easy_excel_doc_props(int $handle, string $propsJson): ?string func easy_excel_doc_props(handle int64, propsJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDocProps(goStr(propsJson))) } //export_php:function easy_excel_custom_prop(int $handle, string $propJson): ?string func easy_excel_custom_prop(handle int64, propJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetCustomProp(goStr(propJson))) } //export_php:function easy_excel_unmerge_cells(int $handle, string $sheet, string $range): ?string func easy_excel_unmerge_cells(handle int64, sheet *C.zend_string, ref *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.UnmergeCells(goStr(sheet), goStr(ref))) } //export_php:function easy_excel_get_merges(int $handle, string $sheet): array func easy_excel_get_merges(handle int64, sheet *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } refs, err := wb.Merges(goStr(sheet)) if err != nil { return pair(nil, err) } list := make([]any, len(refs)) for i, r := range refs { list[i] = r } return pair(list, nil) } //export_php:function easy_excel_get_style(int $handle, string $sheet, string $cell): array func easy_excel_get_style(handle int64, sheet *C.zend_string, cell *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } spec, err := wb.GetStyleSpec(goStr(sheet), goStr(cell)) return pair(spec, err) } //export_php:function easy_excel_get_validations(int $handle, string $sheet): array func easy_excel_get_validations(handle int64, sheet *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } out, err := wb.ValidationsJSON(goStr(sheet)) return pair(out, err) } //export_php:function easy_excel_get_conditionals(int $handle, string $sheet): array func easy_excel_get_conditionals(handle int64, sheet *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } out, err := wb.ConditionalsJSON(goStr(sheet)) return pair(out, err) } //export_php:function easy_excel_get_defined_names(int $handle): array func easy_excel_get_defined_names(handle int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } out, err := wb.DefinedNamesJSON() return pair(out, err) } //export_php:function easy_excel_set_default_style(int $handle, string $styleJson): ?string func easy_excel_set_default_style(handle int64, styleJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetDefaultStyle(goStr(styleJson))) } //export_php:function easy_excel_insert_rows(int $handle, string $sheet, int $row, int $count): ?string func easy_excel_insert_rows(handle int64, sheet *C.zend_string, row int64, count int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.InsertRows(goStr(sheet), int(row), int(count))) } //export_php:function easy_excel_remove_rows(int $handle, string $sheet, int $row, int $count): ?string func easy_excel_remove_rows(handle int64, sheet *C.zend_string, row int64, count int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.RemoveRows(goStr(sheet), int(row), int(count))) } //export_php:function easy_excel_insert_cols(int $handle, string $sheet, int $col, int $count): ?string func easy_excel_insert_cols(handle int64, sheet *C.zend_string, col int64, count int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.InsertCols(goStr(sheet), int(col), int(count))) } //export_php:function easy_excel_remove_cols(int $handle, string $sheet, int $col, int $count): ?string func easy_excel_remove_cols(handle int64, sheet *C.zend_string, col int64, count int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.RemoveCols(goStr(sheet), int(col), int(count))) } //export_php:function easy_excel_move_sheet(int $handle, string $sheet, int $index): ?string func easy_excel_move_sheet(handle int64, sheet *C.zend_string, index int64) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.MoveSheetTo(goStr(sheet), int(index))) } //export_php:function easy_excel_copy_sheet(int $handle, string $from, string $newName): array func easy_excel_copy_sheet(handle int64, from *C.zend_string, newName *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return pair(nil, err) } idx, err := wb.CopySheetTo(goStr(from), goStr(newName)) return pair(int64(idx), err) } //export_php:function easy_excel_sheet_view(int $handle, string $sheet, string $viewJson): ?string func easy_excel_sheet_view(handle int64, sheet *C.zend_string, viewJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetSheetView(goStr(sheet), goStr(viewJson))) } //export_php:function easy_excel_header_footer(int $handle, string $sheet, string $hfJson): ?string func easy_excel_header_footer(handle int64, sheet *C.zend_string, hfJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetHeaderFooter(goStr(sheet), goStr(hfJson))) } //export_php:function easy_excel_page_margins(int $handle, string $sheet, string $marginsJson): ?string func easy_excel_page_margins(handle int64, sheet *C.zend_string, marginsJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetPageMargins(goStr(sheet), goStr(marginsJson))) } //export_php:function easy_excel_set_rich_text(int $handle, string $sheet, string $cell, string $runsJson): ?string func easy_excel_set_rich_text(handle int64, sheet *C.zend_string, cell *C.zend_string, runsJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.SetRichText(goStr(sheet), goStr(cell), goStr(runsJson))) } //export_php:function easy_excel_add_image_bytes(int $handle, string $sheet, string $cell, string $imageJson): ?string func easy_excel_add_image_bytes(handle int64, sheet *C.zend_string, cell *C.zend_string, imageJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.AddImageBytes(goStr(sheet), goStr(cell), goStr(imageJson))) } //export_php:function easy_excel_auto_filter_columns(int $handle, string $sheet, string $range, string $columnsJson): ?string func easy_excel_auto_filter_columns(handle int64, sheet *C.zend_string, ref *C.zend_string, columnsJson *C.zend_string) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } return errOnly(wb.AutoFilterWithColumns(goStr(sheet), goStr(ref), goStr(columnsJson))) } //export_php:function easy_excel_save_csv(int $handle, string $path, string $sheet, string $delimiter, bool $crlf, bool $bom, bool $guardFormulas): ?string func easy_excel_save_csv(handle int64, path *C.zend_string, sheet *C.zend_string, delimiter *C.zend_string, crlf bool, bom bool, guard bool) unsafe.Pointer { wb, err := workbook(handle) if err != nil { return errOnly(err) } opts := core.CsvOptions{UseCRLF: crlf, UseBOM: bom, GuardFormula: guard} if d := goStr(delimiter); d != "" { opts.Delimiter = []rune(d)[0] } return errOnly(wb.SaveCsv(goStr(path), goStr(sheet), opts)) } // --- observability ------------------------------------------------------------------ //export_php:function easy_excel_stats(): array func easy_excel_stats() unsafe.Pointer { return frankenphp.PHPPackedArray([]any{ int64(handles.Len()), gate.MemoryUsed(), }) }