IWorkbook.SaveToStream throws System.IndexOutOfRangeException

165 Views Asked by At

When calling the following code to convert a workbook to a memory stream in order to save it to an external storage system.

private static MemoryStream GetWorkbookStream(IWorkbook workbook)
{
    using var workbookStream = new MemoryStream();
    workbook.SaveToStream(workbookStream, SpreadsheetGearHelper.DefaultFileFormat);
    return workbookStream;
}

An exception is raised:

exception.ClassName System.IndexOutOfRangeException
exception.HResult -2146233080
exception.Message Index was outside the bounds of the array.
exception.RemoteStackIndex  0
exception.Source SpreadsheetGear
exception.StackTraceString  
at sg_楆.续.祦()
at sg_楆.续.祦(sg_룞 A_0, 葴& A_1)
at sg_楆.续.突(葴& A_0)
at sg_䜁.葴.葴(续& A_0)
at sg_䠜.ꫴ.突(续& A_0)
at sg_䠜.鶰.秛(续& A_0)
at sg_䠜.䊕.秛(续& A_0)
at sg_䠜.鶰.鰠(续& A_0, 葴& A_1)
at sg_楆.续.续()
at sg_楆.祦(续& A_0, sg_鹖 A_1)
at sg_楆.祦(sg_ꆧ A_0, 续& A_1)
at sg_楆.骐()
at sg_楆.祦(Boolean A_0)
at sg_楆.突(Boolean A_0)
at sg_䗦.祦(sg_䜁 A_0, 霿 A_1, Stream A_2, FileFormat A_3)
at sg_䗦.SaveToStream(Stream stream, FileFormat fileFormat)

With this exception it is not clear to me what has went wrong inside SpreadsheetGear.

What could be causing this?

1

There are 1 best solutions below

0
Tim Andersen On

Impossible to say for sure with just the information provided.

I will say that the most common cause for these types of exceptions is due to failure to properly use SpreadsheetGear locking API while doing work on a workbook. See IWorkbookSet.GetLock() and ReleaseLock() in the SpreadsheetGear doc for more details on this. But basically, in many scenarios, for routines that involve most SpreadsheetGear API for a workbook (and its containing worksheets, ranges, etc., and including calls to save methods), you must wrap such calls with GetLock() / ReleaseLock(). Doing so ensures that interruptible background calculations are properly suspended, attempted access by other threads to the workbook set are queued, etc. Failure to do so can cause your routine to access the workbook at an unexpected time / unready state, and so lead to all sorts of random problems, such as the exception you are seeing.

Please do read through all of the appropriate documentation, as there is more nuance in its usage. But in terms of your above routine, this might look like the following:

private static MemoryStream GetWorkbookStream(IWorkbook workbook)
{
    // Acquire a lock on the workbook's parent IWorkbookSet.
    workbook.WorkbookSet.GetLock();
    try
    {
        // Do whatever work you need to do on the workbook here.
        using var workbookStream = new MemoryStream();
        workbook.SaveToStream(workbookStream, SpreadsheetGearHelper.DefaultFileFormat);
        return workbookStream;
    }
    catch (Exception ex)
    {
        // Catch and handle exceptions if necessary...
    }
    finally
    {
        // Release the lock on the workbook set.
        workbook.WorkbookSet.ReleaseLock();
    }
}

If the above doesn't apply or help, then you would need to provide a fully but minimally reproducible test case.