Quiero convertir un archivo de Excel en una imagen (cada formato está bien) programáticamente (C#). Actualmente estoy usando Microsoft Interop Libraries & Office 2007, pero no admite guardar en una imagen de forma predeterminada.Programmatically (C#) convertir Excel en una imagen
Así que mi solución alternativa actual es la siguiente:
- Abrir archivo de Excel utilizando Microsoft interoperabilidad;
- Encuentra el rango máximo (que contiene datos);
- Use CopyPicture() en ese rango, que copiará los datos en el Portapapeles.
Ahora la parte difícil (y mis problemas):
Problema 1:
Utilización de la clase .NET portapapeles, yo no soy capaz de obtener los datos exactos copiados desde el portapapeles : los datos son los mismos, pero de alguna manera el formato está distorsionado (la fuente de todo el documento parece ser en negrita y un poco más ilegible mientras que no lo eran); Si pego desde el portapapeles con mspaint.exe, la imagen pegada es correcta (y justo como quiero que sea).
Desensamblé mspaint.exe y encontré una función que está usando (OleGetClipboard) para obtener datos del portapapeles, pero parece que no puedo hacer que funcione en C#/.NET.
Otras cosas que probé fueron los WINAPI de Portapapeles (OpenClipboard, GetClipboardData, CF_ENHMETAFILE), pero los resultados fueron los mismos que con las versiones de .NET.
Problema 2:
El uso de la gama y CopyPicture, si hay alguna imagen en la hoja de Excel, esas imágenes no se copian junto con los datos que rodean al portapapeles.
Parte del código fuente
Excel.Application app = new Excel.Application();
app.Visible = app.ScreenUpdating = app.DisplayAlerts = false;
app.CopyObjectsWithCells = true;
app.CutCopyMode = Excel.XlCutCopyMode.xlCopy;
app.DisplayClipboardWindow = false;
try {
Excel.Workbooks workbooks = null;
Excel.Workbook book = null;
Excel.Sheets sheets = null;
try {
workbooks = app.Workbooks;
book = workbooks.Open(inputFile, false, false, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
sheets = book.Worksheets;
} catch {
Cleanup(workbooks, book, sheets); //Cleanup function calls Marshal.ReleaseComObject for all passed objects
throw;
}
for (int i = 0; i < sheets.Count; i++) {
Excel.Worksheet sheet = (Excel.Worksheet)sheets.get_Item(i + 1);
Excel.Range myrange = sheet.UsedRange;
Excel.Range rowRange = myrange.Rows;
Excel.Range colRange = myrange.Columns;
int rows = rowRange.Count;
int cols = colRange.Count;
//Following is used to find range with data
string startRange = "A1";
string endRange = ExcelColumnFromNumber(cols) + rows.ToString();
//Skip "empty" excel sheets
if (startRange == endRange) {
Excel.Range firstRange = sheet.get_Range(startRange, endRange);
Excel.Range cellRange = firstRange.Cells;
object text = cellRange.Text;
string strText = text.ToString();
string trimmed = strText.Trim();
if (trimmed == "") {
Cleanup(trimmed, strText, text, cellRange, firstRange, myrange, rowRange, colRange, sheet);
continue;
}
Cleanup(trimmed, strText, text, cellRange, firstRange);
}
Excel.Range range = sheet.get_Range(startRange, endRange);
try {
range.CopyPicture(Excel.XlPictureAppearance.xlScreen, Excel.XlCopyPictureFormat.xlPicture);
//Problem here <-------------
//Every attempt to get data from Clipboard fails
} finally {
Cleanup(range);
Cleanup(myrange, rowRange, colRange, sheet);
}
} //end for loop
book.Close(false, Type.Missing, Type.Missing);
workbooks.Close();
Cleanup(book, sheets, workbooks);
} finally {
app.Quit();
Cleanup(app);
GC.Collect();
}
Obtención de datos desde el portapapeles utilizando WINAPI tiene éxito, pero con mala calidad. Fuente:
protected virtual void ClipboardToPNG(string filename) {
if (OpenClipboard(IntPtr.Zero)) {
if (IsClipboardFormatAvailable((int)CLIPFORMAT.CF_ENHMETAFILE)) {
int hEmfClp = GetClipboardDataA((int)CLIPFORMAT.CF_ENHMETAFILE);
if (hEmfClp != 0) {
int hEmfCopy = CopyEnhMetaFileA(hEmfClp, null);
if (hEmfCopy != 0) {
Metafile metafile = new Metafile(new IntPtr(hEmfCopy), true);
metafile.Save(filename, ImageFormat.Png);
}
}
}
CloseClipboard();
}
}
Alguien tiene una solución? (Estoy usando .NET 2.0 por cierto)
podría compartir su código fuente? ¿En qué formato quieres obtener los datos copiados? Como mapa de bits? –