使用OLEDB从Excel文件中检索图片

6

我有一个Excel表格,有两列,第一列是数字,第二列是图片。我希望通过OLEDB连接从C#中读取这些数据,虽然可以轻松读取数字,但是图片没有包含在第二列中,因此在C#中只能获取第一列。

现在,我该如何读取图片?我想从这个Excel表格中提取数字和相关的图片。

3个回答

8

这是一个比较旧的话题,但我想分享一些我的代码。

这个例子假设你有一个Windows应用程序,在上面放置了一个名为“pictureBox1”的Picturebox。

它还假设你添加了对Excel(Microsoft.Office.Interop.Excel)的引用。

图片绑定到工作簿而不是单元格本身,正如Jay所提到的那样。你可以通过使用TopLeftCell和BottomRightCell很容易地找到图像应该放置的位置。

现在,你需要编写一个循环来提取文档中的所有图像,但这部分我会留给你自己完成。

        string file = @"C:\sample.xlsx";

        if(System.IO.File.Exists(file))
        {

            Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
            excelApp.Visible = true; //FOR TESTING ONLY
            Microsoft.Office.Interop.Excel.Workbook wb = excelApp.Workbooks.Open(file,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing,
                                Type.Missing);

            Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets[1];   //Selects the first sheet
            Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)ws.Cells[1, 1];      //Select cell A1
            object cellValue = range.Value2;

            #region Extract the image
            Microsoft.Office.Interop.Excel.Picture pic = (Microsoft.Office.Interop.Excel.Picture)ws.Pictures(1);

            if (pic != null)
            {
                //This code will detect what the region span of the image was
                int startCol = (int)pic.TopLeftCell.Column;
                int startRow = (int)pic.TopLeftCell.Row;
                int endCol = (int)pic.BottomRightCell.Column;
                int endRow = (int)pic.BottomRightCell.Row;


                pic.CopyPicture(Microsoft.Office.Interop.Excel.XlPictureAppearance.xlScreen, Microsoft.Office.Interop.Excel.XlCopyPictureFormat.xlBitmap);
                if (Clipboard.ContainsImage())
                {
                    Image img = Clipboard.GetImage();
                    this.pictureBox1.Image = img;
                }
            }
            #endregion

            //Close the workbook
            wb.Close(false,Type.Missing,Type.Missing);

            //Exit Excel
            excelApp.Quit();
        }

附加说明:如果您在WinForm、WPF中进行操作,它将能够正常工作,因为它需要使用剪贴板(Console不支持)。 - Sruit A.Suk

5

很抱歉,这是不可能的。

图片并没有存储在单元格中,你可以将它们放置在单元格上方,并调整大小以使其看起来像是在单元格中,但它们并没有占据该单元格。

您可以使用VBA和COM互操作来操作工作表的图像内容,但不能使用OLEDB。


2
Nick's answer 对我的 Web 应用程序非常有效,只需进行一些更改即可,它没有将图像复制到剪贴板。
 Thread thread = new Thread(() =>
                {
                    foreach (var pic in ws.Pictures())
                    {
                        if (pic != null)
                        {
                            //This code will detect what the region span of the image was
                            int startCol = pic.TopLeftCell.Column;
                            int startRow = pic.TopLeftCell.Row;
                            int endCol = pic.BottomRightCell.Column;
                            int endRow = pic.BottomRightCell.Row;
                            pic.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                            if (Clipboard.GetDataObject() != null)
                            {
                                Image img = Clipboard.GetImage();
                            }
                        }
                    }
                });
                thread.SetApartmentState(ApartmentState.STA);
                //Set the thread to STA
                thread.Start();
                thread.Join();

对我来说可以。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接