本文介绍如何用matlab控制Excel画画。
对于matlab和Excel你的认识不能仅仅停留在xlsread和xlswrite这两个函数上,其实matlab对Excel的操作远远不止于此,详情请见matlab和Excel的交互。
所谓在Excel中画画,无非就是通过填充Excel单元格的背景色实现像素点的表达,都可以通过matlab中的Excel.Application实现。
try % 打开Excel Excel=actxGetRunningServer('Excel.Application'); catch Excel=actxserver('Excel.application'); end
% 设置Excel可见
Excel.visible=1;
添加工作簿和工作表
Workbook=Excel.Workbooks.Add; Sheet1=Workbook.Sheets.Item(1);
下面实现图像的读取,这里用到了imread函数,可以读取图片的RGB值,用三维的数组存储,数据格式为uint8,但是Excel中是用24位的二进制表示颜色,前8位为B,中间8位为G,后8位为R,所以需要先用double强制转换数据类型。
A=imread('图片路径'); A=double(A);
然后就是分别得到R,G,B:
column=size(A,2); row=size(A,1); Red=A(:,:,1); Green=A(:,:,2); Blue=A(:,:,3);
为了使得颜色设置更加方便,这里我自己写了一个RGB函数,用于将RGB转换成Excel的格式:
function out=RGB(Red,Green,Blue) if nargin~=3 error('输入参数错误,RGB输入参数为3个,分别为RGB,0~255') end if length(Red)==length(Green)&length(Blue)==length(Green) Red=Red; Green=Green*2^8; Blue=Blue*2^16; out=Red+Green+Blue; else error('输入维度不匹配'); end end
得到的输出能够直接给Excel使用。
修改Excel单元格的背景色可以使用以下代码:
Sheet1.Range(范围).Interior.Color = RGB; % 其中Sheet1为工作表,Range内为范围 格式为 'A1' 或‘A1:C3’
为了能够更方便得到范围的正确格式,我也自己写了一个格式转换的函数,将坐标值转换成字母组合:
function Range=Cells(first,second) % ====================================================================== % 输入参数为单个坐标或者左上角以及右上角坐标,返回结果可用于Excel的Range输入 % Cells(first, second); % first = n second = m; 或 first = [n1,m1],second = [n2 m2] % ====================================================================== % 返回结果: % Cells(1,2)---------------------------'A2' % Cells([26*2 1],[26*27 1])------------ 'AZ1:ZZ1' if nargin ==1 if length(first)==2 second=first(2); first=first(1); end elseif nargin>2 error('Cells输入错误,输入单元格坐标或区域的对角坐标'); end if length(first)==length(second)&&length(first)==1 if first<=0||second<=0 error('坐标不能小于1') end if first<=26 charNum=1; elseif first<=26*26+26 charNum=2; else error('图片像素过大,请剪辑'); end switch charNum case 1 if mod(first,26)==0 Column1='Z'; else Column1=char('@'+mod(first,26)); end Range=[Column1 num2str(second)]; case 2 first=first-26; if mod(first,26*26)==0 Column1='Z'; else Column1=char(floor(first/26)+'A'); end if mod(first,26)==0 Column2='Z'; Column1=char(floor(first/26)+'@'); else Column2=char('@'+mod(first,26)); end Range=[Column1 Column2 num2str(second)]; end elseif length(first)==length(second)&&length(first)==2 if first(1)<second(1) error('左上角坐标在右下角坐标前'); end if sum(first>0)+sum(second>0)<4 error('坐标不能小于1') end if first(1)<=26 charNum1=1; elseif first(1)<=26*26+26 charNum1=2; else error('图片像素过大,请剪辑'); end switch charNum1 case 1 if mod(first(1),26)==0 Column11='Z'; else Column11=char('@'+mod(first(1),26)); end Range1=[Column11 num2str(first(2))]; case 2 first(1)=first(1)-26; if mod(first(1),26*26)==0 Column11='Z'; else Column11=char(floor(first(1)/26)+'A'); end if mod(first(1),26)==0 Column12='Z'; Column11=char(floor(first(1)/26)+'@'); else Column12=char('A'+mod(first(1),26)); end Range1=[Column11 Column12 num2str(first(2))]; end if second(1)<=26 charNum2=1; elseif second(1)<=26*26+26 charNum2=2; else error('图片像素过大,请剪辑'); end switch charNum2 case 1 if mod(second(1),26)==0 Column21='Z'; else Column21=char('@'+mod(second(1),26)); end Range2=[Column21 num2str(second(2))]; case 2 second(1)=second(1)-26; if mod(second(1),26*26) Column21='Z'; else Column21=char(floor(second(1)/26)+'A'); end if mod(second(1),26)==0 Column22='Z'; Column21=char(floor(second(1)/26)+'@'); else Column22=char('A'+mod(second(1),26)); end Range2=[Column21 Column22 num2str(second(2))]; end Range=[Range1 ':' Range2]; else error('Cells输入错误,输入单元格坐标或区域的对角坐标'); end
最后通过一个二维的for循环即可实现自动填充,效果如下图:
完整代码如下:
try Excel=actxGetRunningServer('Excel.Application'); catch Excel=actxserver('Excel.application'); end % 设置Excel可见 Excel.visible=1; Workbook=Excel.Workbooks.Add; Sheet1=Workbook.Sheets.Item(1); A=imread('图片路径'); A=double(A); column=size(A,2); row=size(A,1); Red=A(:,:,1); Green=A(:,:,2); Blue=A(:,:,3); color=RGB(Red,Green,Blue); tic for a=1:size(color,2) % a为列数 for b=1:size(color,1) % b为行数 Sheet1.Range(Cells(a,b)).Interior.Color =color(b,a); end end toc Excel.Quit; % 关闭 Excel Excel.delete; % 删除对象