#include "oosxl_module.h"


PyTypeObject WorksheetType;

static void Worksheet_dealloc(WorksheetObject* self)
{
    Py_TYPE(self)->tp_free((PyObject*)self);
}

static PyObject* Worksheet_min_row(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_min_row(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_max_row(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_max_row(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_min_col(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_min_col(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_max_col(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_max_col(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_name(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    const char* name = ws_name(self->handle);
    if (name == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get worksheet name");
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(name);
}

static PyObject* Worksheet_set_name(WorksheetObject* self, PyObject* args)
{
    const char* newname;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &newname))
        return NULL;

    int result = ws_set_name(self->handle, newname);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set worksheet name");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_sheet_type(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_ws_type(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_sheet_state(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_get_ws_state(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_cell_type(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_cell_type(self->handle, row, col);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_contains_formula(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_contains_formula(self->handle, row, col);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_contains_richtext(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_contains_richtext(self->handle, row, col);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_get_num(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    double result = ws_get_num(self->handle, row, col);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_get_text(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    const char* result = ws_get_text(self->handle, row, col);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(result);
}

static PyObject* Worksheet_get_boolean(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_get_boolean(self->handle, row, col);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_get_datetime(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    double result = ws_get_datetime(self->handle, row, col);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_get_richtext(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    RichtextHandle rt_handle = ws_get_richtext(self->handle, row, col);
    if (rt_handle == NULL)
    {
        Py_RETURN_NONE;
    }

    return create_richtext_object(rt_handle);
}

static PyObject* Worksheet_get_formula_expr(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    const char* result = ws_get_formula_expr(self->handle, row, col);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(result);
}

static PyObject* Worksheet_get_error(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_get_error(self->handle, row, col);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_num(WorksheetObject* self, PyObject* args)
{
    int row, col;
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid", &row, &col, &value))
    {
        return NULL;
    }

    int result = ws_set_num(self->handle, row, col, value);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set numeric value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_text(WorksheetObject* self, PyObject* args)
{
    int row, col;
    const char* value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iis", &row, &col, &value))
    {
        return NULL;
    }

    int result = ws_set_text(self->handle, row, col, value);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set text value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_boolean(WorksheetObject* self, PyObject* args)
{
    int row, col, value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iip", &row, &col, &value))
    {
        return NULL;
    }

    int result = ws_set_boolean(self->handle, row, col, value);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set boolean value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_datetime(WorksheetObject* self, PyObject* args)
{
    int row, col;
    double dt;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid", &row, &col, &dt))
    {
        return NULL;
    }

    int result = ws_set_datetime(self->handle, row, col, dt);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set datetime value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_richtext(WorksheetObject* self, PyObject* args)
{
    int row, col;
    PyObject* rt_obj;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiO", &row, &col, &rt_obj))
    {
        return NULL;
    }

    if (!PyObject_TypeCheck(rt_obj, &RichtextType))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a Richtext object");
        return NULL;
    }

    RichtextObject* rt = (RichtextObject*)rt_obj;
    int result = ws_set_richtext(self->handle, row, col, rt->handle);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set richtext value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_error(WorksheetObject* self, PyObject* args)
{
    int row, col, code;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii", &row, &col, &code))
        return NULL;

    int result = ws_set_error(self->handle, row, col, code);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set error value");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula(WorksheetObject* self, PyObject* args)
{
    int row, col;
    const char* expr;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iis", &row, &col, &expr))
    {
        return NULL;
    }

    int result = ws_set_formula(self->handle, row, col, expr);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula_num(WorksheetObject* self, PyObject* args)
{
    int row, col;
    double val;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid", &row, &col, &val))
    {
        return NULL;
    }

    int result = ws_set_formula_num(self->handle, row, col, val);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula with numeric result");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula_string(WorksheetObject* self, PyObject* args)
{
    int row, col;
    const char* s;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iis", &row, &col, &s))
    {
        return NULL;
    }

    int result = ws_set_formula_string(self->handle, row, col, s);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula with string result");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula_boolean(WorksheetObject* self, PyObject* args)
{
    int row, col, b;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iip", &row, &col, &b))
    {
        return NULL;
    }

    int result = ws_set_formula_boolean(self->handle, row, col, b);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula with boolean result");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula_datetime(WorksheetObject* self, PyObject* args)
{
    int row, col;
    double dt;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid", &row, &col, &dt))
    {
        return NULL;
    }

    int result = ws_set_formula_datetime(self->handle, row, col, dt);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula with datetime result");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_formula_error(WorksheetObject* self, PyObject* args)
{
    int row, col, code;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii", &row, &col, &code))
    {
        return NULL;
    }

    int result = ws_set_formula_error(self->handle, row, col, code);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set formula with error result");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_clear_contents(WorksheetObject* self, PyObject* args)
{
    int beginRow, beginCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiii", &beginRow, &beginCol, &endRow, &endCol))
    {
        return NULL;
    }

    ws_clear_contents(self->handle, beginRow, beginCol, endRow, endCol);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_cell_style(WorksheetObject* self, PyObject* args)
{
    int row, col;
    PyObject* style_obj;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiO", &row, &col, &style_obj))
    {
        return NULL;
    }

    if (!PyObject_TypeCheck(style_obj, &StyleType))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a Style object");
        return NULL;
    }

    StyleObject* style = (StyleObject*)style_obj;
    ws_set_cell_style(self->handle, row, col, style->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_cell_style(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    StyleHandle style_handle = ws_cell_style(self->handle, row, col);
    if (style_handle == NULL)
    {
        Py_RETURN_NONE;
    }

    return create_style_object(style_handle);
}

static PyObject* Worksheet_get_cell_style(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    StyleHandle style_handle = ws_get_cell_style(self->handle, row, col);
    if (style_handle == NULL)
    {
        Py_RETURN_NONE;
    }

    return create_style_object(style_handle);
}

static PyObject* Worksheet_set_range_style(WorksheetObject* self, PyObject* args)
{
    int startRow, startCol, stopRow, stopCol;
    PyObject* style_obj;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiiiO", &startRow, &startCol, &stopRow, &stopCol, &style_obj))
    {
        return NULL;
    }

    if (!PyObject_TypeCheck(style_obj, &StyleType))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a Style object");
        return NULL;
    }

    StyleObject* style = (StyleObject*)style_obj;
    ws_set_range_style(self->handle, startRow, startCol, stopRow, stopCol, style->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_is_default_row_height(WorksheetObject* self, PyObject* args)
{
    int start, end = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &start, &end))
    {
        return NULL;
    }

    int result = ws_is_default_row_height(self->handle, start, end);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_get_custom_row_height(WorksheetObject* self, PyObject* args)
{
    int start, end, unit = ROWHEIGHT_POINTS;
    double height;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|i", &start, &end, &unit))
    {
        return NULL;
    }

    int result = ws_get_custom_row_height(self->handle, start, end, &height, unit);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get custom row height");
        return NULL;
    }

    return PyFloat_FromDouble(height);
}

static PyObject* Worksheet_set_custom_row_height(WorksheetObject* self, PyObject* args)
{
    int start, end;
    int unit = ROWHEIGHT_POINTS;
    double height;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid|i", &start, &end, &height, &unit))
        return NULL;

    ws_set_custom_row_height(self->handle, start, end, height, unit);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_is_default_col_width(WorksheetObject* self, PyObject* args)
{
    int start, end = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &start, &end))
    {
        return NULL;
    }

    int result = ws_is_default_col_width(self->handle, start, end);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_get_custom_col_width(WorksheetObject* self, PyObject* args)
{
    int start, end, unit = COLWIDTH_CHARS;
    double width;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|i", &start, &end, &unit))
    {
        return NULL;
    }

    int result = ws_get_custom_col_width(self->handle, start, end, &width, unit);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get custom column width");
        return NULL;
    }

    return PyFloat_FromDouble(width);
}

static PyObject* Worksheet_set_custom_col_width(WorksheetObject* self, PyObject* args)
{
    int start, end;
    double width;
    int unit = COLWIDTH_CHARS;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iid|i", &start, &end, &width, &unit))
        return NULL;

    ws_set_custom_col_width(self->handle, start, end, width, unit);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_row_style(WorksheetObject* self, PyObject* args)
{
    int row;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &row))
    {
        return NULL;
    }

    StyleHandle style_handle = ws_row_style(self->handle, row);
    if (style_handle == NULL)
    {
        Py_RETURN_NONE;
    }

    return create_style_object(style_handle);
}

static PyObject* Worksheet_remove_row_style(WorksheetObject* self, PyObject* args)
{
    int row;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &row))
    {
        return NULL;
    }

    ws_remove_row_style(self->handle, row);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_row_style(WorksheetObject* self, PyObject* args)
{
    int startRow, stopRow;
    PyObject* style_obj;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiO", &startRow, &stopRow, &style_obj))
    {
        return NULL;
    }

    if (!PyObject_TypeCheck(style_obj, &StyleType))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a Style object");
        return NULL;
    }

    StyleObject* style = (StyleObject*)style_obj;
    ws_set_row_style(self->handle, startRow, stopRow, style->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_col_style(WorksheetObject* self, PyObject* args)
{
    int col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &col))
    {
        return NULL;
    }

    StyleHandle style_handle = ws_col_style(self->handle, col);
    if (style_handle == NULL)
    {
        Py_RETURN_NONE;
    }

    return create_style_object(style_handle);
}

static PyObject* Worksheet_remove_col_style(WorksheetObject* self, PyObject* args)
{
    int col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &col))
    {
        return NULL;
    }

    ws_remove_col_style(self->handle, col);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_col_style(WorksheetObject* self, PyObject* args)
{
    int startCol, stopCol;
    PyObject* style_obj;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiO", &startCol, &stopCol, &style_obj))
    {
        return NULL;
    }

    if (!PyObject_TypeCheck(style_obj, &StyleType))
    {
        PyErr_SetString(PyExc_TypeError, "Expected a Style object");
        return NULL;
    }

    StyleObject* style = (StyleObject*)style_obj;
    ws_set_col_style(self->handle, startCol, stopCol, style->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_row_hidden(WorksheetObject* self, PyObject* args)
{
    int row;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &row))
    {
        return NULL;
    }

    int result = ws_row_hidden(self->handle, row);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_row_hidden(WorksheetObject* self, PyObject* args)
{
    int startRow, stopRow, hidden = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|p", &startRow, &stopRow, &hidden))
        return NULL;

    ws_set_row_hidden(self->handle, startRow, stopRow, hidden);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_col_hidden(WorksheetObject* self, PyObject* args)
{
    int col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &col))
    {
        return NULL;
    }

    int result = ws_col_hidden(self->handle, col);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_col_hidden(WorksheetObject* self, PyObject* args)
{
    int startCol, stopCol, hidden = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|p", &startCol, &stopCol, &hidden))
        return NULL;

    ws_set_col_hidden(self->handle, startCol, stopCol, hidden);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_insert_row(WorksheetObject* self, PyObject* args)
{
    int row, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &row, &count))
        return NULL;

    int result = ws_insert_row(self->handle, row, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to insert row");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_delete_row(WorksheetObject* self, PyObject* args)
{
    int begin, end = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &begin, &end))
        return NULL;

    int result = ws_delete_row(self->handle, begin, end);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to delete row");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_insert_col(WorksheetObject* self, PyObject* args)
{
    int col, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &col, &count))
        return NULL;

    int result = ws_insert_col(self->handle, col, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to insert column");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_delete_col(WorksheetObject* self, PyObject* args)
{
    int begin, end = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|i", &begin, &end))
        return NULL;

    int result = ws_delete_col(self->handle, begin, end);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to delete column");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_shift_range_down(WorksheetObject* self, PyObject* args)
{
    int startCol, endCol, startRow, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii|i", &startCol, &endCol, &startRow, &count))
        return NULL;

    int result = ws_shift_range_down(self->handle, startCol, endCol, startRow, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to shift range down");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_shift_range_up(WorksheetObject* self, PyObject* args)
{
    int startCol, endCol, startRow, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii|i", &startCol, &endCol, &startRow, &count))
        return NULL;

    int result = ws_shift_range_up(self->handle, startCol, endCol, startRow, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to shift range up");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_shift_range_right(WorksheetObject* self, PyObject* args)
{
    int startRow, endRow, startCol, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii|i", &startRow, &endRow, &startCol, &count))
        return NULL;

    int result = ws_shift_range_right(self->handle, startRow, endRow, startCol, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to shift range right");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_shift_range_left(WorksheetObject* self, PyObject* args)
{
    int startRow, endRow, startCol, count = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iii|i", &startRow, &endRow, &startCol, &count))
        return NULL;

    int result = ws_shift_range_left(self->handle, startRow, endRow, startCol, count);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to shift range left");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_bg_picture(WorksheetObject* self, PyObject* args)
{
    const char* file;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &file))
    {
        return NULL;
    }

    ws_set_bg_picture(self->handle, file);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_add_cell_image(WorksheetObject* self, PyObject* args)
{
    const char* file;
    int startRow, startCol, stopRow, stopCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "siiii", &file, &startRow, &startCol, &stopRow, &stopCol))
    {
        return NULL;
    }

    int result = ws_add_cell_image(self->handle, file, startRow, startCol, stopRow, stopCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add cell image");
        return NULL;
    }

    return PyLong_FromLong(result);
}

static PyObject* Worksheet_add_image_with_two_cells(WorksheetObject* self, PyObject* args)
{
    const char* file;
    int row1, col1, row2, col2;
    int offset_x1 = 0;
    int offset_y1 = 0;
    int offset_x2 = 0;
    int offset_y2 = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "siiii|iiii", &file, &row1, &col1, &row2, &col2,
                          &offset_x1, &offset_y1, &offset_x2, &offset_y2))
    {
        return NULL;
    }

    int result = ws_add_image_with_two_cells(self->handle, file, row1, col1, row2, col2,
                                             offset_x1, offset_y1, offset_x2, offset_y2);
    if (result < 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add image");
        return NULL;
    }

    return PyLong_FromLong(result);
}

static PyObject* Worksheet_add_image_with_one_cell(WorksheetObject* self, PyObject* args)
{
    const char* file;
    int row, col;
    int width = 0;
    int height = 0;
    double scale = 1.0;
    int offset_x = 0;
    int offset_y = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "sii|iidii", &file, &row, &col, &scale, &offset_x, &offset_y))
        return NULL;

    int result = ws_add_image_with_one_cell(self->handle, file, row, col, width, height, scale, offset_x, offset_y);
    if (result < 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add image");
        return NULL;
    }

    return PyLong_FromLong(result);
}

static PyObject* Worksheet_add_absolute_image(WorksheetObject* self, PyObject* args)
{
    const char* file;
    int x, y;
    int width = 0;
    int height = 0;
    double scale = 1.0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "sii|iid", &file, &x, &y, &width, &height, &scale))
        return NULL;

    int result = ws_add_absolute_image(self->handle, file, x, y, width, height, scale);
    if (result < 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add image");
        return NULL;
    }

    return PyLong_FromLong(result);
}

static PyObject* Worksheet_image_num(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_image_num(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_get_image_id(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
        return NULL;

    int result = ws_get_image_id(self->handle, index);
    if (result < 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get image id");
        return NULL;
    }

    return PyLong_FromLong(result);
}

static PyObject* Worksheet_image_anchor_type(WorksheetObject* self, PyObject* args)
{
    int image_id;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &image_id))
        return NULL;

    int result = ws_image_anchor_type(self->handle, image_id);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_get_anchored_cell(WorksheetObject* self, PyObject* args)
{
    int image_id;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &image_id))
        return NULL;

    int row = 0, col = 0;
    int result = ws_get_anchored_cell(self->handle, image_id, &row, &col);
    if (!result)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get the anchor cell of the image");
        return NULL;
    }

    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_get_absolute_coord(WorksheetObject* self, PyObject* args)
{
    int image_id;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &image_id))
        return NULL;

    int x = 0, y = 0;
    int result = ws_get_absolute_coord(self->handle, image_id, &x, &y);
    if (!result)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get the anchor coordinates of the image");
        return NULL;
    }

    return Py_BuildValue("(ii)", x, y);
}

static PyObject* Worksheet_delete_image(WorksheetObject* self, PyObject* args)
{
    int image_id;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &image_id))
    {
        return NULL;
    }

    ws_delete_image(self->handle, image_id);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_remove_image(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    ws_remove_image(self->handle, row, col);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_remove_absolute_image(WorksheetObject* self, PyObject* args)
{
    int x, y;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &x, &y))
    {
        return NULL;
    }

    ws_remove_absolute_image(self->handle, x, y);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_first_data_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_first_data_cell(self->handle, &row, &col);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to find first data cell");
        return NULL;
    }

    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_last_data_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_last_data_cell(self->handle, &row, &col);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to find last data cell");
        return NULL;
    }

    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_merged_num(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_merged_num(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_merged_range(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    int startRow, startCol, stopRow, stopCol;
    int result = ws_merged_range(self->handle, index, &startRow, &startCol, &stopRow, &stopCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get merge info");
        return NULL;
    }

    return Py_BuildValue("(iiii)", startRow, startCol, stopRow, stopCol);
}

static PyObject* Worksheet_merge(WorksheetObject* self, PyObject* args)
{
    int startRow, startCol, stopRow, stopCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiii", &startRow, &startCol, &stopRow, &stopCol))
    {
        return NULL;
    }

    int result = ws_merge(self->handle, startRow, startCol, stopRow, stopCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to merge cells");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_unmerge(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_unmerge(self->handle, row, col);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to unmerge cells");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_tabledef_count(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_tabledef_count(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_get_tabledef_name(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    const char* result = ws_get_tabledef_name(self->handle, index);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(result);
}

static PyObject* Worksheet_set_tabledef_name(WorksheetObject* self, PyObject* args)
{
    int index;
    const char* new_name;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "is", &index, &new_name))
    {
        return NULL;
    }

    int result = ws_set_tabledef_name(self->handle, index, new_name);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set table definition name");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_get_tabledef(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    TabledefHandle lo_handle = ws_get_tabledef(self->handle, index);
    if (lo_handle == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get table definition");
        return NULL;
    }

    return create_tabledef_object(lo_handle);
}

static PyObject* Worksheet_get_tabledef_by_name(WorksheetObject* self, PyObject* args)
{
    const char* name;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &name))
    {
        return NULL;
    }

    TabledefHandle lo_handle = ws_get_tabledef_by_name(self->handle, name);
    if (lo_handle == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to get table definition by name");
        return NULL;
    }

    return create_tabledef_object(lo_handle);
}

static PyObject* Worksheet_add_tabledef(WorksheetObject* self, PyObject* args)
{
    const char* name;
    int beginRow, beginCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "siiii", &name, &beginRow, &beginCol, &endRow, &endCol))
    {
        return NULL;
    }

    TabledefHandle lo_handle = ws_add_tabledef(self->handle, name, beginRow, beginCol, endRow, endCol);
    if (lo_handle == NULL)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add table definition");
        return NULL;
    }

    return create_tabledef_object(lo_handle);
}

static PyObject* Worksheet_delete_tabledef(WorksheetObject* self, PyObject* args)
{
    const char* name;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &name))
    {
        return NULL;
    }

    int result = ws_delete_tabledef(self->handle, name);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to delete table definition");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_group_rows(WorksheetObject* self, PyObject* args)
{
    int beginRow, endRow, collapsed = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|p", &beginRow, &endRow, &collapsed))
        return NULL;

    ws_group_rows(self->handle, beginRow, endRow, collapsed);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_ungroup_rows(WorksheetObject* self, PyObject* args)
{
    int beginRow, endRow;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &beginRow, &endRow))
    {
        return NULL;
    }

    ws_ungroup_rows(self->handle, beginRow, endRow);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_group_cols(WorksheetObject* self, PyObject* args)
{
    int beginCol, endCol, collapsed = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii|p", &beginCol, &endCol, &collapsed))
        return NULL;

    ws_group_cols(self->handle, beginCol, endCol, collapsed);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_ungroup_cols(WorksheetObject* self, PyObject* args)
{
    int beginCol, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &beginCol, &endCol))
        return NULL;

    ws_ungroup_cols(self->handle, beginCol, endCol);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_row_outline_level(WorksheetObject* self, PyObject* args)
{
    int row, collapsed = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &row))
    {
        return NULL;
    }

    int result = ws_row_outline_level(self->handle, row, &collapsed);
    return Py_BuildValue("(ii)", result, collapsed);
}

static PyObject* Worksheet_col_outline_level(WorksheetObject* self, PyObject* args)
{
    int col, collapsed = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &col))
    {
        return NULL;
    }

    int result = ws_col_outline_level(self->handle, col, &collapsed);
    return Py_BuildValue("(ii)", result, collapsed);
}

static PyObject* Worksheet_max_row_outline_level(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_max_row_outline_level(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_max_col_outline_level(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_max_col_outline_level(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_delete_row_outline(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_delete_row_outline(self->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_delete_col_outline(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_delete_col_outline(self->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_group_summary_below(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_group_summary_below(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_group_summary_below(WorksheetObject* self, PyObject* args)
{
    int below = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &below))
    {
        return NULL;
    }

    ws_set_group_summary_below(self->handle, below);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_group_summary_right(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_group_summary_right(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_group_summary_right(WorksheetObject* self, PyObject* args)
{
    int right = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &right))
    {
        return NULL;
    }

    ws_set_group_summary_right(self->handle, right);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_add_hyperlink(WorksheetObject* self, PyObject* args)
{
    const char* hyperlink;
    int startRow, startCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "siiii", &hyperlink, &startRow, &startCol, &endRow, &endCol))
    {
        return NULL;
    }

    int result = ws_add_hyperlink(self->handle, hyperlink, startRow, startCol, endRow, endCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to add hyperlink");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_hyperlink_num(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_hyperlink_num(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_hyperlink_index(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    int result = ws_hyperlink_index(self->handle, row, col);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_hyperlink(WorksheetObject* self, PyObject* args)
{
    int index, startRow, startCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    const char* result = ws_hyperlink(self->handle, index, &startRow, &startCol, &endRow, &endCol);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return Py_BuildValue("s(iiii)", result, startRow, startCol, endRow, endCol);
}

static PyObject* Worksheet_delete_hyperlink(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    int result = ws_delete_hyperlink(self->handle, index);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to delete hyperlink");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_is_protected(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_is_protected(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_protect(WorksheetObject* self, PyObject* args)
{
    int item = PROTECT_DEFAULT;
    const char* password = NULL;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|iz", &item, &password))
        return NULL;

    int result = ws_protect(self->handle, item, password);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to protect worksheet");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_unprotect(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_unprotect(self->handle);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_protect_cells(WorksheetObject* self, PyObject* args)
{
    int startRow, startCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiii", &startRow, &startCol, &endRow, &endCol))
    {
        return NULL;
    }

    int result = ws_protect_range(self->handle, startRow, startCol, endRow, endCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to protect cells");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_set_editable_range(WorksheetObject* self, PyObject* args)
{
    int startRow, startCol, endRow, endCol;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "iiii", &startRow, &startCol, &endRow, &endCol))
    {
        return NULL;
    }

    int result = ws_set_editable_range(self->handle, startRow, startCol, endRow, endCol);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to allow edit range");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_editable_range_count(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_editable_range_count(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_delete_editable_range(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    int result = ws_delete_editable_range(self->handle, index);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to delete allowed edit range");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_get_editable_range(WorksheetObject* self, PyObject* args)
{
    int index, startRow = 0, startCol = 0, stopRow = 0, stopCol = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    const char* result = ws_get_editable_range(self->handle, index, &startRow, &startCol, &stopRow, &stopCol);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return Py_BuildValue("s(iiii)", result, startRow, startCol, stopRow, stopCol);
}

static PyObject* Worksheet_zoom(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_zoom(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_zoom(WorksheetObject* self, PyObject* args)
{
    int zoom;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &zoom))
    {
        return NULL;
    }

    ws_set_zoom(self->handle, zoom);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_right_to_left(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_right_to_left(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_right_to_left(WorksheetObject* self, PyObject* args)
{
    int right_to_left = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &right_to_left))
        return NULL;

    ws_set_right_to_left(self->handle, right_to_left);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_topleft_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_topleft_cell(self->handle, &row, &col);
    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_set_topleft_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    ws_set_topleft_cell(self->handle, row, col);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_active_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_active_cell(self->handle, &row, &col);
    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_set_active_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    ws_set_active_cell(self->handle, row, col);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_split_cell(WorksheetObject* self, PyObject* args)
{
    int row = 0, col = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    ws_split_cell(self->handle, &row, &col);
    return Py_BuildValue("(ii)", row, col);
}

static PyObject* Worksheet_set_split_cell(WorksheetObject* self, PyObject* args)
{
    int row, col;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "ii", &row, &col))
    {
        return NULL;
    }

    ws_set_split_cell(self->handle, row, col);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_display_gridlines(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_display_gridlines(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_display_gridlines(WorksheetObject* self, PyObject* args)
{
    int show = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &show))
        return NULL;

    ws_set_display_gridlines(self->handle, show);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_row_break_count(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_row_break_count(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_row_break(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    int result = ws_row_break(self->handle, index);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_row_break(WorksheetObject* self, PyObject* args)
{
    int row, pageBreak = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|p", &row, &pageBreak))
    {
        return NULL;
    }

    int result = ws_set_row_break(self->handle, row, pageBreak);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set row break");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_col_break_count(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_col_break_count(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_col_break(WorksheetObject* self, PyObject* args)
{
    int index;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &index))
    {
        return NULL;
    }

    int result = ws_col_break(self->handle, index);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_col_break(WorksheetObject* self, PyObject* args)
{
    int col, pageBreak = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i|p", &col, &pageBreak))
    {
        return NULL;
    }

    int result = ws_set_col_break(self->handle, col, pageBreak);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set column break");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_print_gridlines(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_print_gridlines(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_print_gridlines(WorksheetObject* self, PyObject* args)
{
    int print = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &print))
        return NULL;

    ws_set_print_gridlines(self->handle, print);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_print_headings(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_print_headings(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_print_headings(WorksheetObject* self, PyObject* args)
{
    int print = 0;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &print))
        return NULL;

    ws_set_print_headings(self->handle, print);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_h_centered_printing(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_h_centered_printing(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_h_centered_printing(WorksheetObject* self, PyObject* args)
{
    int centered = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &centered))
    {
        return NULL;
    }

    ws_set_h_centered_printing(self->handle, centered);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_v_centered_printing(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_v_centered_printing(self->handle);
    return PyBool_FromLong(result);
}

static PyObject* Worksheet_set_v_centered_printing(WorksheetObject* self, PyObject* args)
{
    int centered = 1;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "|p", &centered))
    {
        return NULL;
    }

    ws_set_v_centered_printing(self->handle, centered);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_left_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_left_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_left_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_left_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_right_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_right_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_right_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_right_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_top_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_top_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_top_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_top_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_bottom_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_bottom_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_bottom_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_bottom_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_header_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_header_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_header_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_header_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_footer_margin(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    double result = ws_footer_margin(self->handle);
    return PyFloat_FromDouble(result);
}

static PyObject* Worksheet_set_footer_margin(WorksheetObject* self, PyObject* args)
{
    double value;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "d", &value))
    {
        return NULL;
    }

    ws_set_footer_margin(self->handle, value);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_paper(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_paper(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_paper(WorksheetObject* self, PyObject* args)
{
    int paper_code;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &paper_code))
    {
        return NULL;
    }

    int result = ws_set_paper(self->handle, paper_code);
    if (result == 0)
    {
        PyErr_SetString(PyExc_RuntimeError, "Failed to set paper type");
        return NULL;
    }

    Py_RETURN_NONE;
}

static PyObject* Worksheet_print_scale(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_print_scale(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_print_scale(WorksheetObject* self, PyObject* args)
{
    int zoom;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &zoom))
    {
        return NULL;
    }

    ws_set_print_scale(self->handle, zoom);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_page_orientation(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_page_orientation(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_page_orientation(WorksheetObject* self, PyObject* args)
{
    int orientation;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &orientation))
    {
        return NULL;
    }

    ws_set_page_orientation(self->handle, orientation);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_print_errors(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_print_errors(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_print_errors(WorksheetObject* self, PyObject* args)
{
    int way;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &way))
    {
        return NULL;
    }

    ws_set_print_errors(self->handle, way);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_fit_page_height(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_fit_page_height(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_fit_page_height(WorksheetObject* self, PyObject* args)
{
    int num;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &num))
    {
        return NULL;
    }

    ws_set_fit_page_height(self->handle, num);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_fit_page_width(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    int result = ws_fit_page_width(self->handle);
    return PyLong_FromLong(result);
}

static PyObject* Worksheet_set_fit_page_width(WorksheetObject* self, PyObject* args)
{
    int num;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "i", &num))
    {
        return NULL;
    }

    ws_set_fit_page_width(self->handle, num);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_page_header(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    const char* result = ws_page_header(self->handle);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(result);
}

static PyObject* Worksheet_set_page_header(WorksheetObject* self, PyObject* args)
{
    const char* header;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &header))
    {
        return NULL;
    }

    ws_set_page_header(self->handle, header);
    Py_RETURN_NONE;
}

static PyObject* Worksheet_page_footer(WorksheetObject* self, PyObject* args)
{
    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    const char* result = ws_page_footer(self->handle);
    if (result == NULL)
    {
        Py_RETURN_NONE;
    }

    return PyUnicode_FromString(result);
}

static PyObject* Worksheet_set_page_footer(WorksheetObject* self, PyObject* args)
{
    const char* footer;

    if (!check_handle(self->handle, "worksheet"))
        return NULL;

    if (!PyArg_ParseTuple(args, "s", &footer))
    {
        return NULL;
    }

    ws_set_page_footer(self->handle, footer);
    Py_RETURN_NONE;
}

static PyMethodDef Worksheet_methods[] = {
    {"min_row", (PyCFunction)Worksheet_min_row, METH_NOARGS, "Get minimum row index"},
    {"max_row", (PyCFunction)Worksheet_max_row, METH_NOARGS, "Get maximum row index"},
    {"min_col", (PyCFunction)Worksheet_min_col, METH_NOARGS, "Get minimum column index"},
    {"max_col", (PyCFunction)Worksheet_max_col, METH_NOARGS, "Get maximum column index"},

    {"name", (PyCFunction)Worksheet_name, METH_NOARGS, "Get worksheet name"},
    {"set_name", (PyCFunction)Worksheet_set_name, METH_VARARGS, "Set worksheet name"},
    {"sheet_type", (PyCFunction)Worksheet_sheet_type, METH_VARARGS, "Get worksheet type"},
    {"sheet_state", (PyCFunction)Worksheet_sheet_state, METH_VARARGS, "Get worksheet state"},

    {"cell_type", (PyCFunction)Worksheet_cell_type, METH_VARARGS, "Get cell type"},
    {"contains_formula", (PyCFunction)Worksheet_contains_formula, METH_VARARGS, "Check if cell contains formula"},
    {"contains_richtext", (PyCFunction)Worksheet_contains_richtext, METH_VARARGS, "Check if cell contains richtext"},

    {"get_num", (PyCFunction)Worksheet_get_num, METH_VARARGS, "Get numeric value from cell"},
    {"get_text", (PyCFunction)Worksheet_get_text, METH_VARARGS, "Get text value from cell"},
    {"get_boolean", (PyCFunction)Worksheet_get_boolean, METH_VARARGS, "Get boolean value from cell"},
    {"get_datetime", (PyCFunction)Worksheet_get_datetime, METH_VARARGS, "Get datetime value from cell"},
    {"get_richtext", (PyCFunction)Worksheet_get_richtext, METH_VARARGS, "Get richtext from cell"},
    {"get_formula_expr", (PyCFunction)Worksheet_get_formula_expr, METH_VARARGS, "Get formula expression from cell"},
    {"get_error", (PyCFunction)Worksheet_get_error, METH_VARARGS, "Get error code from cell"},

    {"set_num", (PyCFunction)Worksheet_set_num, METH_VARARGS, "Set numeric value in cell"},
    {"set_text", (PyCFunction)Worksheet_set_text, METH_VARARGS, "Set text value in cell"},
    {"set_boolean", (PyCFunction)Worksheet_set_boolean, METH_VARARGS, "Set boolean value in cell"},
    {"set_datetime", (PyCFunction)Worksheet_set_datetime, METH_VARARGS, "Set datetime value in cell"},
    {"set_richtext", (PyCFunction)Worksheet_set_richtext, METH_VARARGS, "Set richtext in cell"},
    {"set_error", (PyCFunction)Worksheet_set_error, METH_VARARGS, "Set error value in cell"},
    {"set_formula", (PyCFunction)Worksheet_set_formula, METH_VARARGS, "Set formula in cell"},
    {"set_formula_num", (PyCFunction)Worksheet_set_formula_num, METH_VARARGS, "Set formula with numeric result"},
    {"set_formula_string", (PyCFunction)Worksheet_set_formula_string, METH_VARARGS, "Set formula with string result"},
    {"set_formula_boolean", (PyCFunction)Worksheet_set_formula_boolean, METH_VARARGS, "Set formula with boolean result"},
    {"set_formula_datetime", (PyCFunction)Worksheet_set_formula_datetime, METH_VARARGS, "Set formula with datetime result"},
    {"set_formula_error", (PyCFunction)Worksheet_set_formula_error, METH_VARARGS, "Set formula with error result"},
    {"clear_contents", (PyCFunction)Worksheet_clear_contents, METH_VARARGS, "Clear cell contents"},

    {"set_cell_style", (PyCFunction)Worksheet_set_cell_style, METH_VARARGS, "Set cell style"},
    {"cell_style", (PyCFunction)Worksheet_cell_style, METH_VARARGS, "Get cell style"},
    {"get_cell_style", (PyCFunction)Worksheet_get_cell_style, METH_VARARGS, "Get cell style"},
    {"set_range_style", (PyCFunction)Worksheet_set_range_style, METH_VARARGS, "Set range style"},

    {"is_default_row_height", (PyCFunction)Worksheet_is_default_row_height, METH_VARARGS, "Check if row has default height"},
    {"get_custom_row_height", (PyCFunction)Worksheet_get_custom_row_height, METH_VARARGS, "Get custom row height"},
    {"set_custom_row_height", (PyCFunction)Worksheet_set_custom_row_height, METH_VARARGS, "Set custom row height"},
    {"is_default_col_width", (PyCFunction)Worksheet_is_default_col_width, METH_VARARGS, "Check if column has default width"},
    {"get_custom_col_width", (PyCFunction)Worksheet_get_custom_col_width, METH_VARARGS, "Get custom column width"},
    {"set_custom_col_width", (PyCFunction)Worksheet_set_custom_col_width, METH_VARARGS, "Set custom column width"},

    {"row_style", (PyCFunction)Worksheet_row_style, METH_VARARGS, "Get row style"},
    {"remove_row_style", (PyCFunction)Worksheet_remove_row_style, METH_VARARGS, "Remove row style"},
    {"set_row_style", (PyCFunction)Worksheet_set_row_style, METH_VARARGS, "Set row style"},
    {"col_style", (PyCFunction)Worksheet_col_style, METH_VARARGS, "Get column style"},
    {"remove_col_style", (PyCFunction)Worksheet_remove_col_style, METH_VARARGS, "Remove column style"},
    {"set_col_style", (PyCFunction)Worksheet_set_col_style, METH_VARARGS, "Set column style"},

    {"row_hidden", (PyCFunction)Worksheet_row_hidden, METH_VARARGS, "Check if row is hidden"},
    {"set_row_hidden", (PyCFunction)Worksheet_set_row_hidden, METH_VARARGS, "Set row hidden"},
    {"col_hidden", (PyCFunction)Worksheet_col_hidden, METH_VARARGS, "Check if column is hidden"},
    {"set_col_hidden", (PyCFunction)Worksheet_set_col_hidden, METH_VARARGS, "Set column hidden"},

    {"insert_row", (PyCFunction)Worksheet_insert_row, METH_VARARGS, "Insert rows"},
    {"delete_row", (PyCFunction)Worksheet_delete_row, METH_VARARGS, "Delete rows"},
    {"insert_col", (PyCFunction)Worksheet_insert_col, METH_VARARGS, "Insert columns"},
    {"delete_col", (PyCFunction)Worksheet_delete_col, METH_VARARGS, "Delete columns"},

    {"shift_range_down", (PyCFunction)Worksheet_shift_range_down, METH_VARARGS, "Shift range down"},
    {"shift_range_up", (PyCFunction)Worksheet_shift_range_up, METH_VARARGS, "Shift range up"},
    {"shift_range_right", (PyCFunction)Worksheet_shift_range_right, METH_VARARGS, "Shift range right"},
    {"shift_range_left", (PyCFunction)Worksheet_shift_range_left, METH_VARARGS, "Shift range left"},

    {"set_bg_picture", (PyCFunction)Worksheet_set_bg_picture, METH_VARARGS, "Set background picture"},
    {"add_cell_image", (PyCFunction)Worksheet_add_cell_image, METH_VARARGS, "Add cell image"},
    {"add_image_with_two_cells", (PyCFunction)Worksheet_add_image_with_two_cells, METH_VARARGS, "Add image with two cells"},
    {"add_image_with_one_cell", (PyCFunction)Worksheet_add_image_with_one_cell, METH_VARARGS, "Add image with one cell"},
    {"add_absolute_image", (PyCFunction)Worksheet_add_absolute_image, METH_VARARGS, "Add absolute image"},
    {"image_num", (PyCFunction)Worksheet_image_num, METH_NOARGS, "Get number of images"},
    {"get_image_id", (PyCFunction)Worksheet_get_image_id, METH_VARARGS, "Get image id"},
    {"image_anchor_type", (PyCFunction)Worksheet_image_anchor_type, METH_VARARGS, "Get anchor type of the image"},
    {"image_anchor_cell", (PyCFunction)Worksheet_get_anchored_cell, METH_VARARGS, "Get anchored cell of the image"},
    {"image_absolute_coord", (PyCFunction)Worksheet_get_absolute_coord, METH_VARARGS, "Get anchor coordinates of the image"},
    {"delete_image", (PyCFunction)Worksheet_delete_image, METH_VARARGS, "Delete image by id"},
    {"remove_image", (PyCFunction)Worksheet_remove_image, METH_VARARGS, "Delete image by anchor cell"},
    {"remove_absolute_image", (PyCFunction)Worksheet_remove_absolute_image, METH_VARARGS, "Delete image by anchor coordinates"},

    {"first_data_cell", (PyCFunction)Worksheet_first_data_cell, METH_NOARGS, "Find first data cell"},
    {"last_data_cell", (PyCFunction)Worksheet_last_data_cell, METH_NOARGS, "Find last data cell"},

    {"merged_num", (PyCFunction)Worksheet_merged_num, METH_NOARGS, "Get number of merged ranges"},
    {"merged_range", (PyCFunction)Worksheet_merged_range, METH_VARARGS, "Get a merged range"},
    {"merge", (PyCFunction)Worksheet_merge, METH_VARARGS, "Merge cells"},
    {"unmerge", (PyCFunction)Worksheet_unmerge, METH_VARARGS, "Unmerge cells"},

    {"tabledef_count", (PyCFunction)Worksheet_tabledef_count, METH_NOARGS, "Get number of table definition"},
    {"get_tabledef_name", (PyCFunction)Worksheet_get_tabledef_name, METH_VARARGS, "Get table definition name"},
    {"set_tabledef_name", (PyCFunction)Worksheet_set_tabledef_name, METH_VARARGS, "Set table definition name"},
    {"get_tabledef", (PyCFunction)Worksheet_get_tabledef, METH_VARARGS, "Get table definition by index"},
    {"get_tabledef_by_name", (PyCFunction)Worksheet_get_tabledef_by_name, METH_VARARGS, "Get table definition by name"},
    {"add_tabledef", (PyCFunction)Worksheet_add_tabledef, METH_VARARGS, "Add table definition"},
    {"delete_tabledef", (PyCFunction)Worksheet_delete_tabledef, METH_VARARGS, "Delete table definition"},

    {"group_rows", (PyCFunction)Worksheet_group_rows, METH_VARARGS, "Group rows"},
    {"ungroup_rows", (PyCFunction)Worksheet_ungroup_rows, METH_VARARGS, "Ungroup rows"},
    {"group_cols", (PyCFunction)Worksheet_group_cols, METH_VARARGS, "Group columns"},
    {"ungroup_cols", (PyCFunction)Worksheet_ungroup_cols, METH_VARARGS, "Ungroup columns"},
    {"row_outline_level", (PyCFunction)Worksheet_row_outline_level, METH_VARARGS, "Get row outline level and collapsed state"},
    {"col_outline_level", (PyCFunction)Worksheet_col_outline_level, METH_VARARGS, "Get column outline level and collapsed state"},
    {"max_row_outline_level", (PyCFunction)Worksheet_max_row_outline_level, METH_NOARGS, "Get maximum row outline level"},
    {"max_col_outline_level", (PyCFunction)Worksheet_max_col_outline_level, METH_NOARGS, "Get maximum column outline level"},
    {"delete_row_outline", (PyCFunction)Worksheet_delete_row_outline, METH_NOARGS, "Delete all row outlines"},
    {"delete_col_outline", (PyCFunction)Worksheet_delete_col_outline, METH_NOARGS, "Delete all column outlines"},
    {"group_summary_below", (PyCFunction)Worksheet_group_summary_below, METH_NOARGS, "Check if group summary is below details"},
    {"set_group_summary_below", (PyCFunction)Worksheet_set_group_summary_below, METH_VARARGS, "Set group summary position (below defaults to True)"},
    {"group_summary_right", (PyCFunction)Worksheet_group_summary_right, METH_NOARGS, "Check if group summary is right of details"},
    {"set_group_summary_right", (PyCFunction)Worksheet_set_group_summary_right, METH_VARARGS, "Set group summary position (right defaults to True)"},

    {"add_hyperlink", (PyCFunction)Worksheet_add_hyperlink, METH_VARARGS, "Add hyperlink"},
    {"hyperlink_num", (PyCFunction)Worksheet_hyperlink_num, METH_NOARGS, "Get number of hyperlinks"},
    {"hyperlink_index", (PyCFunction)Worksheet_hyperlink_index, METH_VARARGS, "Get hyperlink index for cell"},
    {"hyperlink", (PyCFunction)Worksheet_hyperlink, METH_VARARGS, "Get hyperlink info"},
    {"delete_hyperlink", (PyCFunction)Worksheet_delete_hyperlink, METH_VARARGS, "Delete hyperlink"},

    {"is_protected", (PyCFunction)Worksheet_is_protected, METH_NOARGS, "Check if worksheet is protected"},
    {"protect", (PyCFunction)Worksheet_protect, METH_VARARGS, "Protect worksheet"},
    {"unprotect", (PyCFunction)Worksheet_unprotect, METH_NOARGS, "Unprotect worksheet"},
    {"protect_range", (PyCFunction)Worksheet_protect_cells, METH_VARARGS, "Protect specific cell range"},
    {"set_editable_range", (PyCFunction)Worksheet_set_editable_range, METH_VARARGS, "Allow editing in specific range"},
    {"editable_range_count", (PyCFunction)Worksheet_editable_range_count, METH_NOARGS, "Get count of allowed edit ranges"},
    {"get_editable_range", (PyCFunction)Worksheet_get_editable_range, METH_VARARGS, "Get allowed edit range info"},
    {"delete_editable_range", (PyCFunction)Worksheet_delete_editable_range, METH_VARARGS, "Delete allowed edit range"},

    {"zoom", (PyCFunction)Worksheet_zoom, METH_NOARGS, "Get zoom level"},
    {"set_zoom", (PyCFunction)Worksheet_set_zoom, METH_VARARGS, "Set zoom level"},
    {"right_to_left", (PyCFunction)Worksheet_right_to_left, METH_NOARGS, "Check if right-to-left mode"},
    {"set_right_to_left", (PyCFunction)Worksheet_set_right_to_left, METH_VARARGS, "Set right-to-left mode"},
    {"topleft_cell", (PyCFunction)Worksheet_topleft_cell, METH_NOARGS, "Get top-left cell"},
    {"set_topleft_cell", (PyCFunction)Worksheet_set_topleft_cell, METH_VARARGS, "Set top-left cell"},
    {"active_cell", (PyCFunction)Worksheet_active_cell, METH_NOARGS, "Get active cell"},
    {"set_active_cell", (PyCFunction)Worksheet_set_active_cell, METH_VARARGS, "Set active cell"},
    {"split_cell", (PyCFunction)Worksheet_split_cell, METH_NOARGS, "Get split cell position"},
    {"set_split_cell", (PyCFunction)Worksheet_set_split_cell, METH_VARARGS, "Set split cell position"},
    {"display_gridlines", (PyCFunction)Worksheet_display_gridlines, METH_NOARGS, "Check if gridlines are displayed"},
    {"set_display_gridlines", (PyCFunction)Worksheet_set_display_gridlines, METH_VARARGS, "Set gridlines display"},

    {"row_break_count", (PyCFunction)Worksheet_row_break_count, METH_NOARGS, "Get row break count"},
    {"row_break", (PyCFunction)Worksheet_row_break, METH_VARARGS, "Get row break at index"},
    {"set_row_break", (PyCFunction)Worksheet_set_row_break, METH_VARARGS, "Set row break (pageBreak defaults to True)"},
    {"col_break_count", (PyCFunction)Worksheet_col_break_count, METH_NOARGS, "Get column break count"},
    {"col_break", (PyCFunction)Worksheet_col_break, METH_VARARGS, "Get column break at index"},
    {"set_col_break", (PyCFunction)Worksheet_set_col_break, METH_VARARGS, "Set column break (pageBreak defaults to True)"},

    {"print_gridlines", (PyCFunction)Worksheet_print_gridlines, METH_NOARGS, "Check if gridlines are printed"},
    {"set_print_gridlines", (PyCFunction)Worksheet_set_print_gridlines, METH_VARARGS, "Set gridlines printing"},
    {"print_headings", (PyCFunction)Worksheet_print_headings, METH_NOARGS, "Check if headings are printed"},
    {"set_print_headings", (PyCFunction)Worksheet_set_print_headings, METH_VARARGS, "Set headings printing"},
    {"h_centered_printing", (PyCFunction)Worksheet_h_centered_printing, METH_NOARGS, "Check if horizontal centered printing"},
    {"set_h_centered_printing", (PyCFunction)Worksheet_set_h_centered_printing, METH_VARARGS, "Set horizontal centered printing (centered defaults to True)"},
    {"v_centered_printing", (PyCFunction)Worksheet_v_centered_printing, METH_NOARGS, "Check if vertical centered printing"},
    {"set_v_centered_printing", (PyCFunction)Worksheet_set_v_centered_printing, METH_VARARGS, "Set vertical centered printing (centered defaults to True)"},

    {"left_margin", (PyCFunction)Worksheet_left_margin, METH_NOARGS, "Get left margin"},
    {"set_left_margin", (PyCFunction)Worksheet_set_left_margin, METH_VARARGS, "Set left margin"},
    {"right_margin", (PyCFunction)Worksheet_right_margin, METH_NOARGS, "Get right margin"},
    {"set_right_margin", (PyCFunction)Worksheet_set_right_margin, METH_VARARGS, "Set right margin"},
    {"top_margin", (PyCFunction)Worksheet_top_margin, METH_NOARGS, "Get top margin"},
    {"set_top_margin", (PyCFunction)Worksheet_set_top_margin, METH_VARARGS, "Set top margin"},
    {"bottom_margin", (PyCFunction)Worksheet_bottom_margin, METH_NOARGS, "Get bottom margin"},
    {"set_bottom_margin", (PyCFunction)Worksheet_set_bottom_margin, METH_VARARGS, "Set bottom margin"},
    {"header_margin", (PyCFunction)Worksheet_header_margin, METH_NOARGS, "Get header margin"},
    {"set_header_margin", (PyCFunction)Worksheet_set_header_margin, METH_VARARGS, "Set header margin"},
    {"footer_margin", (PyCFunction)Worksheet_footer_margin, METH_NOARGS, "Get footer margin"},
    {"set_footer_margin", (PyCFunction)Worksheet_set_footer_margin, METH_VARARGS, "Set footer margin"},

    {"paper", (PyCFunction)Worksheet_paper, METH_NOARGS, "Get paper type"},
    {"set_paper", (PyCFunction)Worksheet_set_paper, METH_VARARGS, "Set paper type"},
    {"print_scale", (PyCFunction)Worksheet_print_scale, METH_NOARGS, "Get print scale"},
    {"set_print_scale", (PyCFunction)Worksheet_set_print_scale, METH_VARARGS, "Set print scale"},
    {"page_orientation", (PyCFunction)Worksheet_page_orientation, METH_NOARGS, "Get page orientation"},
    {"set_page_orientation", (PyCFunction)Worksheet_set_page_orientation, METH_VARARGS, "Set page orientation"},
    {"print_errors", (PyCFunction)Worksheet_print_errors, METH_NOARGS, "Get print errors setting"},
    {"set_print_errors", (PyCFunction)Worksheet_set_print_errors, METH_VARARGS, "Set print errors setting"},
    {"fit_page_height", (PyCFunction)Worksheet_fit_page_height, METH_NOARGS, "Get fit to page height"},
    {"set_fit_page_height", (PyCFunction)Worksheet_set_fit_page_height, METH_VARARGS, "Set fit to page height"},
    {"fit_page_width", (PyCFunction)Worksheet_fit_page_width, METH_NOARGS, "Get fit to page width"},
    {"set_fit_page_width", (PyCFunction)Worksheet_set_fit_page_width, METH_VARARGS, "Set fit to page width"},

    {"page_header", (PyCFunction)Worksheet_page_header, METH_NOARGS, "Get page header"},
    {"set_page_header", (PyCFunction)Worksheet_set_page_header, METH_VARARGS, "Set page header"},
    {"page_footer", (PyCFunction)Worksheet_page_footer, METH_NOARGS, "Get page footer"},
    {"set_page_footer", (PyCFunction)Worksheet_set_page_footer, METH_VARARGS, "Set page footer"},

    {NULL} /* Sentinel */
};

PyTypeObject WorksheetType = {
    PyVarObject_HEAD_INIT(NULL, 0)
        .tp_name = "oosxl.Worksheet",
    .tp_doc = "Worksheet object",
    .tp_basicsize = sizeof(WorksheetObject),
    .tp_itemsize = 0,
    .tp_flags = Py_TPFLAGS_DEFAULT,
    .tp_new = PyType_GenericNew,
    .tp_dealloc = (destructor)Worksheet_dealloc,
    .tp_methods = Worksheet_methods,
};

PyObject* create_worksheet_object(WorksheetHandle handle)
{
    WorksheetObject* obj = (WorksheetObject*)PyObject_New(WorksheetObject, &WorksheetType);
    if (obj != NULL)
    {
        obj->handle = handle;
    }
    return (PyObject*)obj;
}
