| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #include <boost/tokenizer.hpp>
|
| |
|
| | #include <App/Range.h>
|
| | #include <Base/Exception.h>
|
| |
|
| | #include "Sheet.h"
|
| |
|
| |
|
| | #include "SheetPy.h"
|
| | #include "SheetPy.cpp"
|
| |
|
| |
|
| |
|
| | using namespace Spreadsheet;
|
| | using namespace App;
|
| |
|
| |
|
| | std::string SheetPy::representation() const
|
| | {
|
| | return {"<Sheet object>"};
|
| | }
|
| |
|
| | PyObject* SheetPy::PyMake(struct _typeobject*, PyObject*, PyObject*)
|
| | {
|
| |
|
| | return new SheetPy(new Sheet());
|
| | }
|
| |
|
| |
|
| | int SheetPy::PyInit(PyObject* , PyObject* )
|
| | {
|
| | return 0;
|
| | }
|
| |
|
| |
|
| |
|
| | PyObject* SheetPy::set(PyObject* args)
|
| | {
|
| | char* address;
|
| | char* contents;
|
| |
|
| |
|
| | if (!PyArg_ParseTuple(args, "ss:set", &address, &contents)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | Sheet* sheet = getSheetPtr();
|
| | std::string cellAddress = sheet->getAddressFromAlias(address).c_str();
|
| |
|
| |
|
| | if (!cellAddress.empty()) {
|
| | sheet->setCell(cellAddress.c_str(), contents);
|
| | }
|
| | else {
|
| | Range rangeIter(address);
|
| |
|
| | do {
|
| | sheet->setCell(rangeIter.address().c_str(), contents);
|
| | } while (rangeIter.next());
|
| | }
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::get(PyObject* args)
|
| | {
|
| | const char* address;
|
| | const char* address2 = nullptr;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|s:get", &address, &address2)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | if (address2) {
|
| | auto a1 = getSheetPtr()->getAddressFromAlias(address);
|
| | if (a1.empty()) {
|
| | a1 = address;
|
| | }
|
| | auto a2 = getSheetPtr()->getAddressFromAlias(address2);
|
| | if (a2.empty()) {
|
| | a2 = address2;
|
| | }
|
| | Range range(a1.c_str(), a2.c_str());
|
| | Py::Tuple tuple(range.size());
|
| | int i = 0;
|
| | do {
|
| | App::Property* prop = getSheetPtr()->getPropertyByName(range.address().c_str());
|
| | if (!prop) {
|
| | PyErr_Format(
|
| | PyExc_ValueError,
|
| | "Invalid address '%s' in range %s:%s",
|
| | range.address().c_str(),
|
| | address,
|
| | address2
|
| | );
|
| | return nullptr;
|
| | }
|
| | tuple.setItem(i++, Py::Object(prop->getPyObject(), true));
|
| | } while (range.next());
|
| | return Py::new_reference_to(tuple);
|
| | }
|
| | }
|
| | PY_CATCH;
|
| |
|
| | App::Property* prop = this->getSheetPtr()->getPropertyByName(address);
|
| |
|
| | if (!prop) {
|
| | PyErr_Format(PyExc_ValueError, "Invalid cell address or property: %s", address);
|
| | return nullptr;
|
| | }
|
| | return prop->getPyObject();
|
| | }
|
| |
|
| | PyObject* SheetPy::getContents(PyObject* args)
|
| | {
|
| | char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getContents", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | try {
|
| | Sheet* sheet = getSheetPtr();
|
| | std::string addr = sheet->getAddressFromAlias(strAddress);
|
| |
|
| | if (addr.empty()) {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | else {
|
| | address = stringToAddress(addr.c_str());
|
| | }
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | std::string contents;
|
| | const Cell* cell = this->getSheetPtr()->getCell(address);
|
| |
|
| | if (cell) {
|
| | cell->getStringContent(contents);
|
| | }
|
| |
|
| | return Py::new_reference_to(Py::String(contents));
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | PyObject* SheetPy::clear(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | int all = 1;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|p:clear", &strAddress, &all)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | Range rangeIter(strAddress);
|
| | do {
|
| | this->getSheetPtr()->clear(*rangeIter, all);
|
| | } while (rangeIter.next());
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::clearAll(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| |
|
| | this->getSheetPtr()->clearAll();
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::importFile(PyObject* args)
|
| | {
|
| | const char* filename;
|
| | const char* delimiter = "\t";
|
| | const char* quoteChar = "\"";
|
| | const char* escapeChar = "\\";
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|sss:importFile", &filename, &delimiter, "eChar, &escapeChar)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | if (getSheetPtr()->importFromFile(filename, delimiter[0], quoteChar[0], escapeChar[0])) {
|
| | return Py::new_reference_to(Py::Boolean(true));
|
| | }
|
| | else {
|
| | return Py::new_reference_to(Py::Boolean(false));
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::exportFile(PyObject* args)
|
| | {
|
| | const char* filename;
|
| | const char* delimiter = "\t";
|
| | const char* quoteChar = "\"";
|
| | const char* escapeChar = "\\";
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|sss:exportFile", &filename, &delimiter, "eChar, &escapeChar)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | if (getSheetPtr()->exportToFile(filename, delimiter[0], quoteChar[0], escapeChar[0])) {
|
| | return Py::new_reference_to(Py::Boolean(true));
|
| | }
|
| | else {
|
| | return Py::new_reference_to(Py::Boolean(false));
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::mergeCells(PyObject* args)
|
| | {
|
| | const char* range;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:mergeCells", &range)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->mergeCells(Range(range));
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::splitCell(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:splitCell", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | CellAddress address;
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->splitCell(address);
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::insertColumns(PyObject* args)
|
| | {
|
| | const char* column;
|
| | int count;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:insertColumns", &column, &count)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->insertColumns(decodeColumn(column), count);
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::removeColumns(PyObject* args)
|
| | {
|
| | const char* column;
|
| | int count;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:removeColumns", &column, &count)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->removeColumns(decodeColumn(column), count);
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::insertRows(PyObject* args)
|
| | {
|
| | const char* row;
|
| | int count;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:insertRows", &row, &count)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->insertRows(decodeRow(std::string(row)), count);
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::removeRows(PyObject* args)
|
| | {
|
| | const char* row;
|
| | int count;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:removeRows", &row, &count)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | getSheetPtr()->removeRows(decodeRow(std::string(row)), count);
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::setStyle(PyObject* args)
|
| | {
|
| | const char* cell;
|
| | PyObject* value;
|
| | std::set<std::string> style;
|
| | const char* options = "replace";
|
| |
|
| | if (!PyArg_ParseTuple(args, "sO|s:setStyle", &cell, &value, &options)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | if (PySet_Check(value)) {
|
| | PyObject* copy = PySet_New(value);
|
| |
|
| | while (PySet_Size(copy) > 0) {
|
| | PyObject* item = PySet_Pop(copy);
|
| |
|
| |
|
| | if (PyUnicode_Check(item)) {
|
| | style.insert(PyUnicode_AsUTF8(item));
|
| | }
|
| | else {
|
| | std::string error = std::string("type of the set need to be a string, not ")
|
| | + item->ob_type->tp_name;
|
| | PyErr_SetString(PyExc_TypeError, error.c_str());
|
| | Py_DECREF(copy);
|
| | return nullptr;
|
| | }
|
| | }
|
| | Py_DECREF(copy);
|
| | }
|
| | else if (PyUnicode_Check(value)) {
|
| | using namespace boost;
|
| |
|
| | escaped_list_separator<char> e('\0', '|', '\0');
|
| | std::string line = PyUnicode_AsUTF8(value);
|
| | tokenizer<escaped_list_separator<char>> tok(line, e);
|
| |
|
| | for (tokenizer<escaped_list_separator<char>>::iterator i = tok.begin(); i != tok.end(); ++i) {
|
| | style.insert(*i);
|
| | }
|
| | }
|
| | else {
|
| | std::string error = std::string("style must be either set or string, not ")
|
| | + value->ob_type->tp_name;
|
| | PyErr_SetString(PyExc_TypeError, error.c_str());
|
| | return nullptr;
|
| | }
|
| |
|
| | if (strcmp(options, "replace") == 0) {
|
| | Range rangeIter(cell);
|
| | do {
|
| | getSheetPtr()->setStyle(*rangeIter, style);
|
| | } while (rangeIter.next());
|
| | }
|
| | else if (strcmp(options, "add") == 0) {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | std::set<std::string> oldStyle;
|
| | const Cell* cell = getSheetPtr()->getCell(*rangeIter);
|
| |
|
| |
|
| | if (cell) {
|
| | cell->getStyle(oldStyle);
|
| | }
|
| |
|
| | for (const auto& it : oldStyle) {
|
| | style.insert(it);
|
| | }
|
| |
|
| |
|
| | getSheetPtr()->setStyle(*rangeIter, style);
|
| | } while (rangeIter.next());
|
| | }
|
| | else if (strcmp(options, "remove") == 0) {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | std::set<std::string> oldStyle;
|
| | const Cell* cell = getSheetPtr()->getCell(*rangeIter);
|
| |
|
| |
|
| | if (cell) {
|
| | cell->getStyle(oldStyle);
|
| | }
|
| |
|
| | for (const auto& it : style) {
|
| | oldStyle.erase(it);
|
| | }
|
| |
|
| |
|
| | getSheetPtr()->setStyle(*rangeIter, oldStyle);
|
| | } while (rangeIter.next());
|
| | }
|
| | else if (strcmp(options, "invert") == 0) {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | std::set<std::string> oldStyle;
|
| | std::set<std::string> newStyle;
|
| | const Cell* cell = getSheetPtr()->getCell(*rangeIter);
|
| |
|
| |
|
| | if (cell) {
|
| | cell->getStyle(oldStyle);
|
| | newStyle = oldStyle;
|
| | }
|
| |
|
| | for (const auto& i : style) {
|
| | if (oldStyle.find(i) == oldStyle.end()) {
|
| |
|
| | newStyle.insert(i);
|
| | }
|
| | else {
|
| |
|
| | newStyle.erase(i);
|
| | }
|
| | }
|
| |
|
| |
|
| | getSheetPtr()->setStyle(*rangeIter, newStyle);
|
| | } while (rangeIter.next());
|
| | }
|
| | else {
|
| | PyErr_SetString(
|
| | PyExc_ValueError,
|
| | "Optional parameter must be either 'replace', 'add', 'remove', or 'invert'"
|
| | );
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::getStyle(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getStyle", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | std::set<std::string> style;
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| |
|
| | if (cell && cell->getStyle(style)) {
|
| | PyObject* s = PySet_New(nullptr);
|
| |
|
| | for (const auto& i : style) {
|
| | PySet_Add(s, PyUnicode_FromString(i.c_str()));
|
| | }
|
| |
|
| | return s;
|
| | }
|
| | else {
|
| | Py_INCREF(Py_None);
|
| | return Py_None;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setDisplayUnit(PyObject* args)
|
| | {
|
| | const char* cell;
|
| | const char* value;
|
| |
|
| | if (!PyArg_ParseTuple(args, "ss:setDisplayUnit", &cell, &value)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | getSheetPtr()->setDisplayUnit(*rangeIter, value);
|
| | } while (rangeIter.next());
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::setAlias(PyObject* args)
|
| | {
|
| | CellAddress address;
|
| | const char* strAddress;
|
| | PyObject* value;
|
| |
|
| | if (!PyArg_ParseTuple(args, "sO:setAlias", &strAddress, &value)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | Base::PyTypeCheck(&value, &PyUnicode_Type, "String or None expected");
|
| | getSheetPtr()->setAlias(address, value ? PyUnicode_AsUTF8(value) : "");
|
| | Py_Return;
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getAlias(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getAlias", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | CellAddress address(strAddress);
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| | std::string alias;
|
| |
|
| | if (cell && cell->getAlias(alias)) {
|
| | return Py::new_reference_to(Py::String(alias));
|
| | }
|
| | else {
|
| | Py_Return;
|
| | }
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getCellFromAlias(PyObject* args)
|
| | {
|
| | const char* alias;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getAlias", &alias)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | std::string address = getSheetPtr()->getAddressFromAlias(alias);
|
| |
|
| | if (!address.empty()) {
|
| | return Py::new_reference_to(Py::String(address));
|
| | }
|
| | else {
|
| | Py_Return;
|
| | }
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getDisplayUnit(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getDisplayUnit", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| |
|
| | Spreadsheet::DisplayUnit unit;
|
| |
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| |
|
| | if (cell && cell->getDisplayUnit(unit)) {
|
| | return Py::new_reference_to(Py::String(unit.stringRep));
|
| | }
|
| | else {
|
| | Py_Return;
|
| | }
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setAlignment(PyObject* args)
|
| | {
|
| | const char* cell;
|
| | PyObject* value;
|
| | int alignment = 0;
|
| | const char* options = "replace";
|
| |
|
| | if (!PyArg_ParseTuple(args, "sO|s:setAlignment", &cell, &value, &options)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | if (PySet_Check(value)) {
|
| |
|
| | PyObject* copy = PySet_New(value);
|
| | int n = PySet_Size(copy);
|
| |
|
| | while (n-- > 0) {
|
| | PyObject* item = PySet_Pop(copy);
|
| |
|
| | if (PyUnicode_Check(item)) {
|
| | alignment = Cell::decodeAlignment(PyUnicode_AsUTF8(item), alignment);
|
| | }
|
| | else {
|
| | std::string error = std::string("type of the key need to be a string, not")
|
| | + item->ob_type->tp_name;
|
| | PyErr_SetString(PyExc_TypeError, error.c_str());
|
| | Py_DECREF(copy);
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | Py_DECREF(copy);
|
| | }
|
| | else if (PyUnicode_Check(value)) {
|
| |
|
| | using namespace boost;
|
| |
|
| | escaped_list_separator<char> e('\0', '|', '\0');
|
| | std::string line = PyUnicode_AsUTF8(value);
|
| | tokenizer<escaped_list_separator<char>> tok(line, e);
|
| |
|
| | for (tokenizer<escaped_list_separator<char>>::iterator i = tok.begin(); i != tok.end(); ++i) {
|
| | if (!i->empty()) {
|
| | alignment = Cell::decodeAlignment(*i, alignment);
|
| | }
|
| | }
|
| | }
|
| | else {
|
| | std::string error = std::string("style must be either set or string, not ")
|
| | + value->ob_type->tp_name;
|
| | PyErr_SetString(PyExc_TypeError, error.c_str());
|
| | return nullptr;
|
| | }
|
| |
|
| |
|
| | if (strcmp(options, "replace") == 0) {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | getSheetPtr()->setAlignment(*rangeIter, alignment);
|
| | } while (rangeIter.next());
|
| | }
|
| | else if (strcmp(options, "keep") == 0) {
|
| | Range rangeIter(cell);
|
| |
|
| | do {
|
| | int oldAlignment = 0;
|
| | const Cell* cell = getSheetPtr()->getCell(*rangeIter);
|
| |
|
| | if (cell) {
|
| | cell->getAlignment(oldAlignment);
|
| | }
|
| |
|
| | if (alignment & Cell::ALIGNMENT_VERTICAL) {
|
| | oldAlignment &= ~Cell::ALIGNMENT_VERTICAL;
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_HORIZONTAL) {
|
| | oldAlignment &= ~Cell::ALIGNMENT_HORIZONTAL;
|
| | }
|
| |
|
| | getSheetPtr()->setAlignment(*rangeIter, alignment | oldAlignment);
|
| | } while (rangeIter.next());
|
| | }
|
| | else {
|
| | PyErr_SetString(PyExc_ValueError, "Optional parameter must be either 'replace' or 'keep'");
|
| | return nullptr;
|
| | }
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* SheetPy::getAlignment(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getAlignment", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| |
|
| | int alignment;
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| | if (cell && cell->getAlignment(alignment)) {
|
| | PyObject* s = PySet_New(nullptr);
|
| |
|
| | if (alignment & Cell::ALIGNMENT_LEFT) {
|
| | PySet_Add(s, PyUnicode_FromString("left"));
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_HCENTER) {
|
| | PySet_Add(s, PyUnicode_FromString("center"));
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_RIGHT) {
|
| | PySet_Add(s, PyUnicode_FromString("right"));
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_TOP) {
|
| | PySet_Add(s, PyUnicode_FromString("top"));
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_VCENTER) {
|
| | PySet_Add(s, PyUnicode_FromString("vcenter"));
|
| | }
|
| | if (alignment & Cell::ALIGNMENT_BOTTOM) {
|
| | PySet_Add(s, PyUnicode_FromString("bottom"));
|
| | }
|
| |
|
| | return s;
|
| | }
|
| | else {
|
| | Py_INCREF(Py_None);
|
| | return Py_None;
|
| | }
|
| | }
|
| |
|
| | static float decodeFloat(const PyObject* obj)
|
| | {
|
| | if (PyFloat_Check(obj)) {
|
| | return PyFloat_AsDouble((PyObject*)obj);
|
| | }
|
| | else if (PyLong_Check(obj)) {
|
| | return PyLong_AsLong((PyObject*)obj);
|
| | }
|
| | throw Base::TypeError("Float or integer expected");
|
| | }
|
| |
|
| | static void decodeColor(PyObject* value, Base::Color& c)
|
| | {
|
| | if (PyTuple_Check(value)) {
|
| | if (PyTuple_Size(value) < 3 || PyTuple_Size(value) > 4) {
|
| | throw Base::TypeError("Tuple must be either of 3 or 4 floats/ints.");
|
| | }
|
| |
|
| | c.r = decodeFloat(PyTuple_GetItem(value, 0));
|
| | c.g = decodeFloat(PyTuple_GetItem(value, 1));
|
| | c.b = decodeFloat(PyTuple_GetItem(value, 2));
|
| | if (PyTuple_Size(value) == 4) {
|
| | c.a = decodeFloat(PyTuple_GetItem(value, 3));
|
| | return;
|
| | }
|
| | else {
|
| | c.a = 1.0;
|
| | }
|
| | }
|
| | else {
|
| | throw Base::TypeError("Tuple required.");
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setForeground(PyObject* args)
|
| | {
|
| | try {
|
| | const char* range;
|
| | PyObject* value;
|
| | Base::Color c;
|
| |
|
| | if (!PyArg_ParseTuple(args, "sO:setForeground", &range, &value)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | decodeColor(value, c);
|
| |
|
| | Range rangeIter(range);
|
| | do {
|
| | getSheetPtr()->setForeground(*rangeIter, c);
|
| | } while (rangeIter.next());
|
| | Py_Return;
|
| | }
|
| | catch (const Base::TypeError& e) {
|
| | PyErr_SetString(PyExc_TypeError, e.what());
|
| | return nullptr;
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getForeground(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getForeground", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Base::Color c;
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| | if (cell && cell->getForeground(c)) {
|
| | PyObject* t = PyTuple_New(4);
|
| |
|
| | PyTuple_SetItem(t, 0, Py::new_reference_to(Py::Float(c.r)));
|
| | PyTuple_SetItem(t, 1, Py::new_reference_to(Py::Float(c.g)));
|
| | PyTuple_SetItem(t, 2, Py::new_reference_to(Py::Float(c.b)));
|
| | PyTuple_SetItem(t, 3, Py::new_reference_to(Py::Float(c.a)));
|
| |
|
| | return t;
|
| | }
|
| | else {
|
| | Py_INCREF(Py_None);
|
| | return Py_None;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setBackground(PyObject* args)
|
| | {
|
| | try {
|
| | const char* strAddress;
|
| | PyObject* value;
|
| | Base::Color c;
|
| |
|
| | if (!PyArg_ParseTuple(args, "sO:setBackground", &strAddress, &value)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | decodeColor(value, c);
|
| | Range rangeIter(strAddress);
|
| |
|
| | do {
|
| | getSheetPtr()->setBackground(*rangeIter, c);
|
| | } while (rangeIter.next());
|
| | Py_Return;
|
| | }
|
| | catch (const Base::TypeError& e) {
|
| | PyErr_SetString(PyExc_TypeError, e.what());
|
| | return nullptr;
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getBackground(PyObject* args)
|
| | {
|
| | const char* strAddress;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:setStyle", &strAddress)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | address = stringToAddress(strAddress);
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Base::Color c;
|
| | const Cell* cell = getSheetPtr()->getCell(address);
|
| | if (cell && cell->getBackground(c)) {
|
| | PyObject* t = PyTuple_New(4);
|
| |
|
| | PyTuple_SetItem(t, 0, Py::new_reference_to(Py::Float(c.r)));
|
| | PyTuple_SetItem(t, 1, Py::new_reference_to(Py::Float(c.g)));
|
| | PyTuple_SetItem(t, 2, Py::new_reference_to(Py::Float(c.b)));
|
| | PyTuple_SetItem(t, 3, Py::new_reference_to(Py::Float(c.a)));
|
| |
|
| | return t;
|
| | }
|
| | else {
|
| | Py_INCREF(Py_None);
|
| | return Py_None;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setColumnWidth(PyObject* args)
|
| | {
|
| | const char* columnStr;
|
| | int width;
|
| | CellAddress address;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:setColumnWidth", &columnStr, &width)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | std::string cellAddr = std::string(columnStr) + "1";
|
| |
|
| | address = stringToAddress(cellAddr.c_str());
|
| | getSheetPtr()->setColumnWidth(address.col(), width);
|
| | Py_Return;
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getColumnWidth(PyObject* args)
|
| | {
|
| | const char* columnStr;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getColumnWidth", &columnStr)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | CellAddress address(std::string(columnStr) + "1");
|
| |
|
| | return Py::new_reference_to(Py::Long(getSheetPtr()->getColumnWidth(address.col())));
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::setRowHeight(PyObject* args)
|
| | {
|
| | const char* rowStr;
|
| | int height;
|
| |
|
| | if (!PyArg_ParseTuple(args, "si:setRowHeight", &rowStr, &height)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | CellAddress address("A" + std::string(rowStr));
|
| |
|
| | getSheetPtr()->setRowHeight(address.row(), height);
|
| | Py_Return;
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::getRowHeight(PyObject* args)
|
| | {
|
| | const char* rowStr;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s:getRowHeight", &rowStr)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | try {
|
| | CellAddress address("A" + std::string(rowStr));
|
| |
|
| | return Py::new_reference_to(Py::Long(getSheetPtr()->getRowHeight(address.row())));
|
| | }
|
| | catch (const Base::Exception& e) {
|
| | PyErr_SetString(PyExc_ValueError, e.what());
|
| | return nullptr;
|
| | }
|
| | }
|
| |
|
| | PyObject* SheetPy::touchCells(PyObject* args)
|
| | {
|
| | const char* address;
|
| | const char* address2 = nullptr;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|s:touchCells", &address, &address2)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | std::string a1 = getSheetPtr()->getAddressFromAlias(address);
|
| | if (a1.empty()) {
|
| | a1 = address;
|
| | }
|
| |
|
| | std::string a2;
|
| | if (!address2) {
|
| | a2 = a1;
|
| | }
|
| | else {
|
| | a2 = getSheetPtr()->getAddressFromAlias(address2);
|
| | if (a2.empty()) {
|
| | a2 = address2;
|
| | }
|
| | }
|
| | getSheetPtr()->touchCells(Range(a1.c_str(), a2.c_str()));
|
| | Py_Return;
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | PyObject* SheetPy::recomputeCells(PyObject* args)
|
| | {
|
| | const char* address;
|
| | const char* address2 = nullptr;
|
| |
|
| | if (!PyArg_ParseTuple(args, "s|s:touchCells", &address, &address2)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | std::string a1 = getSheetPtr()->getAddressFromAlias(address);
|
| | if (a1.empty()) {
|
| | a1 = address;
|
| | }
|
| |
|
| | std::string a2;
|
| | if (!address2) {
|
| | a2 = a1;
|
| | }
|
| | else {
|
| | a2 = getSheetPtr()->getAddressFromAlias(address2);
|
| | if (a2.empty()) {
|
| | a2 = address2;
|
| | }
|
| | }
|
| | getSheetPtr()->recomputeCells(Range(a1.c_str(), a2.c_str()));
|
| | Py_Return;
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | PyObject* SheetPy::getUsedCells(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | auto usedCells = getSheetPtr()->getCells()->getUsedCells();
|
| | Py::List pyCellList;
|
| | for (const auto& cell : usedCells) {
|
| | pyCellList.append(Py::String(cell.toString()));
|
| | }
|
| | return Py::new_reference_to(pyCellList);
|
| | }
|
| |
|
| | PyObject* SheetPy::getUsedRange(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | auto usedRange = getSheetPtr()->getCells()->getUsedRange();
|
| | if (!std::get<0>(usedRange).isValid()) {
|
| | Py_Return;
|
| | }
|
| | Py::Tuple pyTuple(2);
|
| | pyTuple[0] = Py::String(std::get<0>(usedRange).toString());
|
| | pyTuple[1] = Py::String(std::get<1>(usedRange).toString());
|
| | return Py::new_reference_to(pyTuple);
|
| | }
|
| |
|
| | PyObject* SheetPy::getNonEmptyCells(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | auto nonEmptyCells = getSheetPtr()->getCells()->getNonEmptyCells();
|
| | Py::List pyCellList;
|
| | for (const auto& cell : nonEmptyCells) {
|
| | pyCellList.append(Py::String(cell.toString()));
|
| | }
|
| | return Py::new_reference_to(pyCellList);
|
| | }
|
| |
|
| | PyObject* SheetPy::getNonEmptyRange(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | auto nonEmptyRange = getSheetPtr()->getCells()->getNonEmptyRange();
|
| | Py::Tuple pyTuple(2);
|
| | pyTuple[0] = Py::String(std::get<0>(nonEmptyRange).toString());
|
| | pyTuple[1] = Py::String(std::get<1>(nonEmptyRange).toString());
|
| | return Py::new_reference_to(pyTuple);
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | PyObject* SheetPy::getCustomAttributes(const char*) const
|
| | {
|
| | return nullptr;
|
| | }
|
| |
|
| | int SheetPy::setCustomAttributes(const char*, PyObject*)
|
| | {
|
| | return 0;
|
| | }
|
| |
|