在EXCEL中插入内存中的图片(VSTO)

    Excel中一般是通过Worksheet.Shapes.AddPicture方法添加图片,方法的参数格式为:
    AddPicture([In] string Filename,    [In] MsoTriState LinkToFile,    [In] MsoTriState SaveWithDocument,    [In] float Left,    [In] float Top,    [In] float Width,    [In] float Height);
    其中Filename必须是一个uri路径,内存中的图片对象则没有办法使用此方法插入。
    我们的项目是一个SmartClient的VSTO项目,当时总有一个意识在支配我,那就是尽可能不要访问本地资源,而如果内存中的图片不写到本地又该如何插入到EXCEL中呢?Google吧,结果搜到一个连他自己都说“Heavyweight”的解决方案,那就是在本地临时创建一个最小型的HTTP Server,将内存中的图片数据交给它,然后由它再展交给AddPicture,代码如下:
None.gifusing System;
None.gif
using System.IO;
None.gif
using System.Net;
None.gif
using System.Net.Sockets;
None.gif
using System.Text;
None.gif
using System.Threading;
None.gif
None.gif
namespace YourNameSpace
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class LocalWebServer:IDisposable
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private TcpListener myListener;
InBlock.gif        
private static readonly Guid terminationGuid = new Guid("{7b0d9a9d-fbec-4fe5-8ea7-fc3b313510fc}");
InBlock.gif        
byte[] contentsToServe;
InBlock.gif        Thread thread;
InBlock.gif        
string fileName;
InBlock.gif        
int myPort;
InBlock.gif
InBlock.gif        
//The constructor which makee the TcpListener start listening on the
InBlock.gif        
//given port. It also creates a Thread on the method StartListen(). 
InBlock.gif

InBlock.gif        
public LocalWebServer(int port, string fileName, byte[] contents)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//start listing on the given port
InBlock.gif
                myListener = new TcpListener(IPAddress.Parse("127.0.0.1"), port);
InBlock.gif                contentsToServe 
= contents;
InBlock.gif                
this.fileName = fileName;
InBlock.gif                
this.myPort = port;
InBlock.gif
InBlock.gif                myListener.Start();
InBlock.gif                System.Diagnostics.Debug.WriteLine(
"Web Server Runningdot.gif Press ^C to Stopdot.gif");
InBlock.gif
InBlock.gif                
//start the thread which calls the method 'StartListen'
InBlock.gif
                Thread th = new Thread(new ThreadStart(StartListen));
InBlock.gif                
this.thread = th;
InBlock.gif                th.Start();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                System.Diagnostics.Debug.WriteLine(
"An Exception Occurred while Listening :" + e.ToString());
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void SendHeader(string sHttpVersion, string sMIMEHeader, int iTotBytes, string sStatusCode, TcpClient tcpClient)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            StringBuilder sBuffer 
= new StringBuilder();
InBlock.gif            
// if Mime type is not provided set default to text/html
InBlock.gif

InBlock.gif            
if (string.IsNullOrEmpty(sMIMEHeader))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                sMIMEHeader 
= "text/xml";  // Default Mime Type is text/xml
ExpandedSubBlockEnd.gif
            }

InBlock.gif
InBlock.gif            sBuffer.Append(sHttpVersion);
InBlock.gif            sBuffer.AppendLine(sStatusCode);
InBlock.gif            sBuffer.AppendLine(
"Server: VSTOServer");
InBlock.gif            sBuffer.Append(
"Content-Type: ");
InBlock.gif            sBuffer.AppendLine(sMIMEHeader);
InBlock.gif            sBuffer.AppendLine(
"Accept-Ranges: bytes");
InBlock.gif            sBuffer.Append(
"Content-Length: ");
InBlock.gif            sBuffer.AppendLine(iTotBytes.ToString());
InBlock.gif            sBuffer.AppendLine(
"");
InBlock.gif
InBlock.gif            Byte[] bSendData 
= Encoding.ASCII.GetBytes(sBuffer.ToString());
InBlock.gif            SendToBrowser(bSendData, tcpClient);
InBlock.gif            System.Diagnostics.Debug.WriteLine(
"Total Bytes : " + iTotBytes.ToString());
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void SendToBrowser(Byte[] bSendData, TcpClient tcpClient)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if (tcpClient.Connected)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    NetworkStream stream 
= tcpClient.GetStream();
InBlock.gif                    stream.Write(bSendData, 
0, bSendData.Length);
InBlock.gif                    stream.Flush();
ExpandedSubBlockEnd.gif                }

InBlock.gif                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    System.Diagnostics.Debug.WriteLine(
"Connection Droppeddot.gif.");
ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception e)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                System.Diagnostics.Debug.WriteLine(String.Format(
"Error Occurred : {0} ", e));
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void StartListen()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            
int iStartPos = 0;
InBlock.gif            String sErrorMessage;
InBlock.gif            
while (true)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//Accept a new connection
InBlock.gif
                using (TcpClient tcpClient = myListener.AcceptTcpClient())
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if (tcpClient.Connected)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
dot.gif{
InBlock.gif                        System.Diagnostics.Debug.WriteLine(String.Format(
"\nClient Connected!!\n==================\nClient IP {0}\n", tcpClient.Client.RemoteEndPoint));
InBlock.gif                        NetworkStream stream 
= tcpClient.GetStream();
InBlock.gif                        
//make a byte array and receive data from the client 
InBlock.gif
                        Byte[] bReceive = new Byte[1024];
InBlock.gif                        
int i = stream.Read(bReceive, 0, bReceive.Length);
InBlock.gif                        
//Convert Byte to String
InBlock.gif
                        string sBuffer = Encoding.ASCII.GetString(bReceive);
InBlock.gif                        
// Look for HTTP request
InBlock.gif
                        iStartPos = sBuffer.IndexOf("HTTP"1);
InBlock.gif                        
// Get the HTTP text and version e.g. it will return "HTTP/1.1"
InBlock.gif
                        string sHttpVersion = sBuffer.Substring(iStartPos, 8);
InBlock.gif                        
//At present we will only deal with GET type
InBlock.gif                        
// if OPTION received, still OK
InBlock.gif
                        if (!sBuffer.StartsWith("GET"))
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            System.Diagnostics.Debug.WriteLine(
"Only Get Method is supported..");
InBlock.gif                            SendHeader(sHttpVersion, 
null0" 501 Not Implemented", tcpClient);
InBlock.gif                            
continue;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
if (sBuffer.Contains(terminationGuid.ToString()))
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            SendHeader(sHttpVersion, 
null0" 200 OK", tcpClient);
InBlock.gif                            
break;
ExpandedSubBlockEnd.gif                        }

InBlock.gif                        
if (!sBuffer.Contains(fileName))
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
dot.gif{
InBlock.gif                            sErrorMessage 
= "<H2>404 Error! File Does Not Existdot.gif</H2>";
InBlock.gif                            SendHeader(sHttpVersion, 
"", sErrorMessage.Length, " 404 Not Found", tcpClient);
InBlock.gif                            SendToBrowser(Encoding.ASCII.GetBytes(sErrorMessage), tcpClient);
InBlock.gif                            
continue;
ExpandedSubBlockEnd.gif                        }

InBlock.gif
InBlock.gif                        SendHeader(sHttpVersion, 
null, contentsToServe.Length, " 200 OK", tcpClient);
InBlock.gif                        SendToBrowser(contentsToServe, tcpClient);
ExpandedSubBlockEnd.gif                    }

ExpandedSubBlockEnd.gif                }

ExpandedSubBlockEnd.gif            }

InBlock.gif            myListener.Stop();
ExpandedSubBlockEnd.gif        }

InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
IDisposable Members#region IDisposable Members
InBlock.gif        
public void Dispose()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Send a termination request to stop the web server
InBlock.gif
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:" + myPort + "/" + terminationGuid.ToString());
InBlock.gif            WebResponse response 
= request.GetResponse();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif        
#endregion

InBlock.gif
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
    调用时可以使用这个方法:
None.gif        private void AddPictureByWeb(Excel.Worksheet worksheet, string fileName, byte[] contents, float left, float top, float width, float height)
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif{
InBlock.gif            
// Use any private port in the range 49152–65535
InBlock.gif
            int portNumber = 50213;
InBlock.gif            fileName 
= System.Web.HttpUtility.UrlEncode(fileName);
InBlock.gif            
using (new LocalWebServer(portNumber, fileName, contents))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// the request will land with the WebServer object in this process
InBlock.gif
                string url = @"http://localhost:" + portNumber + "/" + fileName;
InBlock.gif                worksheet.Shapes.AddPicture(url, Office.MsoTriState.msoFalse, Office.MsoTriState.msoTrue,
InBlock.gif                                   left, top, width, height);
ExpandedSubBlockEnd.gif            }

ExpandedBlockEnd.gif        }

None.gif
    内存的图片数据交给byte[] contents即可。
    当这个方案成功后,我却突然开了窍,既然是VSTO的项目,一般来说需要客户端FullTrust许可,那么写到本地临时目录中根本不成问题呀,何苦如此大动干戈呢?于是:
None.gifdot.gif.
None.gifBitmap image 
= new Bitmap(new MemoryStream(buffer))
None.gifimage.Save(filePath, ImageFormat.Jpeg);
None.gifworksheet.Shapes.AddPicture(filePath, Office.MsoTriState.msoFalse,  Office.MsoTriState.msoTrue, left, top, width, height);
None.gifFile.Delete(filePath);
None.gifdot.gif.

转载于:https://www.cnblogs.com/dotAge/archive/2006/09/14/494790.html

工具: 【批量导入图片】 功能: 根据名称批量地导入图片 特点: 1.速度快:导入100图片只需要2秒钟 2.位置准:每张图片都导入到名称后面的单元格中,且刚好和单元格一样大,不会让多张图片重叠 3.大小灵活:导入的图片可以随心所欲定义其大小,且所有图片都占用相同的大小空间。但却保持图片导入前的比例,不会变形。 4.名称灵活:可以使用近似匹配。例如有两张名为“诺基亚8310”、“诺基亚7600”的图片,只需要在单元格输入“诺基亚”就行了,导入图片时可以将“诺基亚”开头的图片全部导入。 5.数量灵活:对于多个图片符合同一单元格名称的状况,可以将所有图片全部导入到其右边的单元格。 6.附件功能:图片导入到工作表后,将Excel默认的图片名“图片1”、“图片2”还原为图片本来的名称。 工具: 【隔行插入行】 功能: 对工作表隔行插入行,或者隔列插入列 特点: 1.可以每隔M行插入N行,其中N和M可以自己指定 2.可以每隔M列插入N列,其中N和M可以自己指定 3.起始行或结束行或者起始列、结束列也可以自己指定 工具: 【区域定位工具】 功能: 可以基于用户指定的条件选择相应的单元格,弥补Excel的不足 特点: 1.对于数值,可以使用所有比较运算符查找数据,Excel本身的定位不能定位于大于、小于某值的区域。 2.对于文本,可以定位于指定的字符,也可以定位于指定字符以外的所有字符。且支持通配符。 3.定位于可以指定区域,包括“选择区域”、“已用区域”和“可见区域”。这比Excel本身的查找更全面。 4.支持双条件查找,例如定位于从60到100的所有数据区域。或者不包括60到100的所有区域。 工具: 【根据工资计算钞票面额张数】 功能: 根据工资计算需要发工资时需要多少张100元、50元、20元、10元等等面额的钞票数量 特点: 1.可以选择一个区域进行操作,批量计算。 2.钞票的面额可以自己定义。 3.不仅计算每个人员需要的钞票张数,还对所有面额钞票汇总。 工具: 【建立工作表目录】 功能: 将当前工用簿中所有工作表建立目录,且产生链接 特点: 1.一键生成工作表目录。 2.单击目录中任意表名可以跳转至该工作表。 工具: 【建立文件目录】 功能: 将指定目录下所有文件建立目录于工作表中 特点: 1.可自由定义目标文件的路径。 2.允许选择目录是否产生链接。 3.可以对子目录中的文件建立目录,不管文件夹中有多少个子文件夹。 4.可以多次执行工具,从而将建立不同文件夹中的文件目录。程序自动将其分置于不同的列中。 工具: 【工作簿拆分】 功能: 将指定工作簿的每个工作表拆分成单独的工作簿 特点: 1.自由选定存放路径。 2.提是拆分后是否保留公式的选项。 3.可以自由定义参与拆分的工作表名 工具: 【工作表拆分】 功能: 将当前工作表的数据按条件拆分成多个工作表 特点: 1.可以自由选择条件所有列。 2.可以设定标题行数,标题不参与拆分。 3.可以自由定义折分条件。 4.可以选择折分成多工作表后是否保留原有公式。 工具: 【合并工作簿】 功能: 将多个具有相同格式的工作簿中所有工作表合并为一个工作簿的多工作表中,也可以将一个工作簿的所有工作表合并到一个工作表 特点: 1.多工作簿合并时,可以自由指定待合并工作簿的目录路径。 2.可以选择将多工作簿合并到同工作表还是同工作簿。 3.对于多个工作簿中具有同名工作表时,可以选择是否合并工作表。 4.进以定义参与合并的工作簿名。即所选文件夹中存在多工作簿,可以对部分执行合并。 5.如果仅对一个工作簿中的工作表进行合并,那么选择“多工作表合并”。 6.对工作表合并时,允许选择参与合并的工作表名。即既可全部参与合并也可以部分工作表参与合并。 7.合并前需要将当前工作簿保存。 工具: 【选区背景着色】 功能: 将选择区域或者选区所在行、列用醒目的颜色标识,便于查看 特点: 1.着色的对象有“选区”、“行”、“列”以及“行列”可选。 2.可选颜色包括6种。 3.可以随时启用、禁用着色功能。 4.程序具有记忆功能。即保存上次的设置。 工具: 【小写转大写】 功能: 将阿拉伯数字转换成人民币大写形式 特点: 1.可以批量操作。 2.可以同时选择多个区域再执行工具。 3.几百个单元格数据瞬间完成转换。 工具: 【大写转小写】 功能: 将人民币大写转换成阿拉伯数字 特点: 1.可以批量操作。 2.可以同时选择多个区域再执行工具。 3.几百个单元格数据瞬间完成转换。 工具: 【批量新建或复制工作表】 功能: 批量新建或者工作表 特点: 1.操作灵活:可以选择新建或者复制。 2.批量操作:可以一次性建立或者复制1到255个。 3.高速操作:建立或者复制255个工作表三秒钟不到即可完成。 4.方向自由:可以定义新表在当前表之前或者之后。 5.命名灵活:对于表名有规律的创建或者复制新表,可以选择“从单元格创建”。 工具: 【批量加解密】 功能: 对当前工作簿中所有工作表或者指定的部分工作表进行加、解密 特点: 1.可以灵活的指定加、解密工作表名。 2.对100个工作表加密或者解密不超过3秒钟。 3.本工个适用于多工作表使用相同密码保护,否则请手工操作。 4.其中解密是知道密码的前提下进行批量解密,而非绿色。 工具: 【生成工资条】 功能: 高效的工资条设计工具 特点: 1.瞬间将工资明细表生成工资条,方便打印并裁剪。 2.生成的工资与工资条之间有一个空行,供剪裁用。可以自定义其高度。 3.可以自己定义工资条头的行数,不同公司可能有不需要标题行。 4.只要类似工资条的信息都可以用本工具生成,例社保资料、成绩通知条等等。 工具: 【删除工资条】 功能: 删除前一工具生成的工资条头 特点: 1.可以由用户指定标题行数,使其适用面更广。 2.瞬间删除工资条标题信息,还原为明细表。 工具: 【反向选择】 功能: 对当前数据区域进行反向选择,即定位于未选择的区域 特点: 1.可以由用户指定标题行数,使其适用面更广。 2.瞬间删除工资条标题信息,还原为明细表。 备注:工具通用于Excel 2003和 EXCEL 2007 工具安装: 必须先解压,然后双击“安装.EXE" 如果需要删除工具,则双击“删除.EXE”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值