Limitations and API Differences

Introduction

Aspose Cells provides powerful spreadsheet manipulation capabilities across multiple platforms. While the Java library is the original implementation, the Python via Java package (aka Aspose.Cells for Python via Java) simply wraps the Java API to enable Python developers to leverage the same functionality.

Although both libraries share the same core engine, there are noticeable limitations and API differences that developers need to be aware of when moving code between the two environments or when writing cross‐platform examples. This article highlights the most important differences and demonstrates how to achieve the same tasks in Java, Python (via Java) code.

Note
The examples below are stand‐alone, runnable snippets. All file paths are relative (e.g., ./Data/Sample.xlsx) so they work out‐of‐the‐box when placed in a typical project folder structure.


1. Namespace & Package Structure

Platform Core Namespace / Package
Java com.aspose.cells
Python via Java asposecells (The wrapper – the Java classes are accessed through asposecells.api)

Example

Java

import com.aspose.cells.*;

public class NamespaceDemo {
    public static void main(String[] args) throws Exception {
        // Create a workbook using the Java namespace
        Workbook workbook = new Workbook();
        System.out.println("Java API: Workbook created.");
    }
}

Python via Java

import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook

# Create a workbook using the Python wrapper
workbook = Workbook()
print("Python via Java API: Workbook created.")
jpype.shutdownJVM()

2. Object Instantiation & Constructors

Feature Java Python via Java
Default constructor new Workbook() Workbook()
Load from file new Workbook("file.xlsx") Workbook("file.xlsx")
Load from stream new Workbook(stream) Workbook(stream)
Memory stream handling Uses java.io.InputStream Uses java.io.ByteArrayInputStream (wrapped)

Example – Loading from a stream

Java

import com.aspose.cells.*;
import java.io.FileInputStream;

public class LoadFromStream {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream("./Data/Sample.xlsx")) {
            Workbook wb = new Workbook(fis);
            System.out.println("Loaded workbook with " + wb.getWorksheets().getCount() + " sheets.");
        }
    }
}

Python via Java

import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook

def load_workbook_from_bytes(data: bytes):
    from jpype import JClass, JArray
    from jpype.types import JByte
    ByteArrayInputStream = JClass("java.io.ByteArrayInputStream")
    JByteArray = JArray(JByte)
    byte_array = JByteArray(data)
    stream = ByteArrayInputStream(byte_array)
    return Workbook(stream)

with open("./Data/Sample.xlsx", "rb") as f:
    workbook = load_workbook_from_bytes(f.read())

jpype.shutdownJVM()

3. Data Types & Collections

Concept Java Python via Java
List of Worksheets WorksheetCollection (indexer get(int)) Same as Java (wrapper)
Cell value type Object (auto‐converted) Object (auto‐converted)
Enums com.aspose.cells.FileFormatType Same enum accessed via wrapper: asposecells.api.FileFormatType
Nullable types Not applicable (Java uses primitives) Same as Java

Example – Accessing a cell value

Java

import com.aspose.cells.*;

public class CellValue {
    public static void main(String[] args) throws Exception {
        Workbook wb = new Workbook("./Data/Sample.xlsx");
        Worksheet sheet = wb.getWorksheets().get(0);
        Cell cell = sheet.getCells().get("A1");
        System.out.println("Java: A1 = " + cell.getStringValue());
    }
}

Python via Java

import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook

wb = Workbook("./Data/Sample.xlsx")
sheet = wb.getWorksheets().get(0)
cell = sheet.getCells().get("A1")
print(f"Python via Java: A1 = {cell.getStringValue()}")
jpype.shutdownJVM()

4. Memory Management & Garbage Collection

Aspect Java Python via Java
Garbage collection JVM GC JVM GC (via JPype) + Python GC
Explicit disposal Not required (but you can call dispose() on Workbook to free native resources) Same method exists: workbook.dispose()

Example – Releasing native resources

Java

import com.aspose.cells.*;

public class DisposeDemo {
    public static void main(String[] args) throws Exception {
        Workbook wb = new Workbook("./Data/Sample.xlsx");
        // Perform operations...
        wb.dispose(); // Explicitly release native memory
    }
}

Python via Java

import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook

wb = Workbook("./Data/Sample.xlsx")
# Perform operations...
wb.dispose()   # Releases native memory used by the Java engine

jpype.shutdownJVM()

5. Exception Types & Handling

Exception Java Python via Java
File format error com.aspose.cells.Exception (Message contains “File format not supported”) Same Java exception wrapped as a generic Exception in Python
License not set com.aspose.cells.LicenseException Same wrapper exception
Out‐of‐memory java.lang.OutOfMemoryError (or com.aspose.cells.Exception) Propagates as JavaException in JPype

Example – Handling a missing license

Java

import com.aspose.cells.*;

public class LicenseDemo {
    public static void main(String[] args) {
        try {
            License lic = new License();
            lic.setLicense("./License/Aspose.Cells.Java.lic");
        } catch (Exception ex) {
            System.err.println("Java: License error – " + ex.getMessage());
        }
    }
}

Python via Java

import jpype
import asposecells
jpype.startJVM()
from asposecells.api import License

try:
  lic = License()
  lic.setLicense("./License/Aspose.Cells.Python.lic")
except Exception as e:  # Java exception is wrapped
  print(f"Python via Java: License error - {e}")

jpype.shutdownJVM()

6. Feature Availability Gaps

Feature Java Python via Java Remarks
Chart rendering to image Full support (Chart.toImage()) Supported via same method No gap
PDF/A‐3b export Available from v22.12 Available (requires Java 8+) No gap
Saving as SpreadsheetML (XLSX‐XML) Supported Not exposed in the Python wrapper (requires manual Java call)
Thread‐safe usage Documented as not thread‐safe without external sync Same limitation Must synchronize access when using from multiple Python threads

7. Build & Deployment Considerations

Aspect Java Python via Java
Runtime JRE 8+ (or JDK) JPype + JRE 8+ (bundled in the wheel)
Native libraries libaspose-cells-java.so / .dll inside the JAR Same native binaries extracted to a temp folder at runtime
Distribution JAR file (≈ 60 MB) Wheel (aspose-cells-xx.xx-py3-none-any.whl) that bundles the JAR
Platform‐specific issues Need to set java.library.path for native lib on some OSes Same requirement; wrapper attempts to set it automatically

8. Migrating Code: From Python via Java to .NET

Below is a complete end‐to‐end example that reads a workbook, modifies a cell, and saves it as PDF. The same logical steps are shown for all three platforms, making the migration path crystal clear.

Java

// ./Examples/Java/ConvertToPdf.java
import com.aspose.cells.*;

public class ConvertToPdf {
    public static void main(String[] args) throws Exception {
        // Load workbook
        Workbook wb = new Workbook("./Data/Sample.xlsx");
        Worksheet ws = wb.getWorksheets().get(0);

        // Change a cell value
        Cell cell = ws.getCells().get("B2");
        cell.putValue("Converted from Java");

        // Save as PDF
        wb.save("./Output/Result.pdf", SaveFormat.Pdf);
        System.out.println("PDF saved at ./Output/Result.pdf");
    }
}

Python via Java

# ./Examples/Python/ConvertToPdf.py
import jpype
import asposecells
jpype.startJVM()
from asposecells.api import Workbook, SaveFormat

# Load workbook
wb = Workbook("./Data/Sample.xlsx")
ws = wb.getWorksheets().get(0)

# Change a cell value
cell = ws.getCells().get("B2")
cell.putValue("Converted from Python")

# Save as PDF
wb.save("./Output/Result.pdf", SaveFormat.PDF)
print("PDF saved at ./Output/Result.pdf")
jpype.shutdownJVM()

All three snippets compile and run as‐is (provided the relative folders exist). This demonstrates how the API surface remains consistent, while language‐specific syntactic differences are isolated to object creation, method calls, and exception handling.