Открыть в памяти XML-строку как книгу Excel без сохранения с помощью Windows Forms C#

У меня есть строка excel (которую я построил) в памяти; код выглядит примерно так:

public static void exportToExcel()
        {
            const string startExcelXML = "<xml version>\r\n<Workbook " +
                  "xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"\r\n"
+
                  " xmlns:o=\"urn:schemas-microsoft-com:office:office\"\r\n " +
                  "xmlns:x=\"urn:schemas-    microsoft-com:office:" +
                  "excel\"\r\n xmlns:ss=\"urn:schemas-microsoft-com:"
+
                  "office:spreadsheet\">\r\n <Styles>\r\n " +
                  "<Style ss:ID=\"Default\" ss:Name=\"Normal\">\r\n " +
                  "<Alignment ss:Vertical=\"Bottom\"/>\r\n <Borders/>" +
                  "\r\n <Font/>\r\n <Interior/>\r\n <NumberFormat/>" +
                  "\r\n <Protection/>\r\n </Style>\r\n " +
                  "<Style ss:ID=\"BoldColumn\">\r\n <Font " +
                  "x:Family=\"Swiss\" ss:Bold=\"1\"/>\r\n </Style>\r\n " +
                  "<Style     ss:ID=\"StringLiteral\">\r\n <NumberFormat" +
                  " ss:Format=\"@\"/>\r\n </Style>\r\n <Style " +
                  "ss:ID=\"Decimal\">\r\n <NumberFormat/>\r\n </Style>\r\n " +
                  "<Style ss:ID=\"Integer\">\r\n <NumberFormat "
+
                  "ss:Format=\"0\"/>\r\n </Style>\r\n <Style " +
                  "ss:ID=\"DateLiteral\">\r\n <NumberFormat " +
                  "ss:Format=\"dd/mm/yyyy;@\"/>\r\n </Style>\r\n " +
                  "</Styles>\r\n ";
            const string endExcelXML = "</Workbook>";

            int sheetCount = 1;
            StringBuilder sb = new StringBuilder();

            sb.Append(startExcelXML);
            sb.Append("<Worksheet ss:Name=\"Sheet" + sheetCount + "\">");
            sb.Append("<Table>");
            sb.Append("<Row>");
            sb.Append("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
            sb.Append("Home country");
            sb.Append("</Data></Cell>");
            sb.Append("<Cell ss:StyleID=\"BoldColumn\"><Data ss:Type=\"String\">");
            sb.Append("Expatriation Type");
            sb.Append("</Data></Cell>");
            sb.Append("</Row>");
            sb.Append("<Row>");
     sb.Append("<Cell ss:StyleID=\"StringLiteral\">" +
      "<Data ss:Type=\"String\">");
     sb.Append("Singapore");
     sb.Append("</Data></Cell>");
     sb.Append("<Cell ss:StyleID=\"StringLiteral\">" +
      "<Data ss:Type=\"String\">");
     sb.Append("Benchmark");
     sb.Append("</Data></Cell>");
            sb.Append("</Row>");
            sb.Append("</Table>");
            sb.Append(" </Worksheet>");
            sb.Append(endExcelXML);
        }

Я могу открыть файл как лист Excel, только если я сохраню файл физически; но есть ли другой способ просто открыть строку xml из памяти в виде листа excel?


person MSV Muthu    schedule 27.01.2010    source источник
comment
Как вы открываете его из файловой системы?   -  person    schedule 27.01.2010
comment
На данный момент мы сохраняем на физический диск и открываем файл с помощью объекта Excel. Мы хотим избежать сохранения в виде файла на физический диск пользователя.   -  person MSV Muthu    schedule 28.01.2010
comment
Как пользователь VB, я не могу понять, почему C# настолько малоизвестен в том, что касается XML-литералы.   -  person Shimmy Weitzhandler    schedule 23.12.2010


Ответы (2)


Я думаю, что вам понадобится какая-то реализация файла с отображением памяти.

Однако я считаю, что .NET 4.0 будет иметь встроенную поддержку MemoryMappedFile.

Вы можете найти другие реализации .net с помощью поисковой системы.

person Jay    schedule 27.01.2010
comment
Я искал MemoryMappedFile и получил несколько реализаций в .net. Одной из таких реализаций является filemap-2.0.2.zip. Я все еще проверяю ее, но на первый взгляд она выглядит немного сложной. Неужели так сложно просто открыть поток с помощью приложения? - person MSV Muthu; 28.01.2010
comment
Да, это довольно сложно. Честно говоря, я не думаю, что это стоит усилий — запись этой строки в файловую систему не займет много времени. - person Jay; 28.01.2010
comment
Да; это то, о чем я думал. Мы это не реализуем. Теперь мы изменили наше требование и запрашиваем у пользователя место для сохранения файла, а затем сохраняем его в этом месте. - person MSV Muthu; 28.01.2010

я точно не знаю, но большинство объектов автоматизации Microsoft поддерживают IPersist или IPersistStream, что может позволить вам загружать из потока в памяти.

Что-то вроде (псевдокод):

xl = new Office.ExcelApplication;
(xl as IPersistStream).Load(myMemoryStream);

Можно использовать вспомогательную функцию оболочки CreateStreamOnHGlobal для создайте оболочку IStream вокруг некоторой памяти:

functionCreateStreamOnMemory(pData: Pointer; nCount: DWORD): IStream;
var
    hMem: HGLOBAL;
    dwError: DWORD;
    p: Pointer;
begin
    hMem := GlobalAlloc(GMEM_MOVEABLE or GMEM_NODISCARD, nCount); 
       //CreateStreamOnHGlobal says "The handle must be 
       //allocated as movable and nondiscardable."
    if hMem = 0 then
        RaiseLastWin32Error;

    p := GlobalLock(hMem);
    if p = nil then
    begin
        dwError := GetLastError;
        GlobalFree(hMem);
        raise EWin32Error.Create('Could not lock global memory object: '+SysErrorMessage(dwError));
    end;
    try
        CopyMemory(p, pData, nCount);
    finally
        GlobalUnlock(hMem);
    end;

    OleCheck(CreateStreamOnHGlobal(hMem, True, Result)); //Because we pass True, the stream will take care of freeing the HGLOBAL when the stream is released
end;

Вставьте свою строку в память и посмотрите, загрузится ли она.

person Ian Boyd    schedule 28.01.2010