function matrix2WordEq(matrixIn, varargin) %matrix2WordEq(M) % Copy the content of a Matlab matrix to a Word Equation matrix through the % Windows clipboard. % % Once this function is executed, the user has 5 seconds (default) to % click over the Word Equation box before Matlab begins to copy the values. % % In the case of matrices larger than 225 cells, the matrix structure must % be manually created before calling this function (it is a Microsoft % Word limitation). % % If values are not being copied properly, increase the CopyPause time. % Ex: matrix2WordEq(M,'CopyPause',0.7); % %************************************************************************** %Syntax: %************************************************************************** % matrix2WordEq(M) % matrix2WordEq(M, Name, Value, ...) % % Input Arguments: % (Required) % M - The matrix to be copied. % % Name-Value Pair Arguments: % (Optional) % InitPause - Time (in seconds) given to the user to navigate to % the word document and select the eqation field. % (5 seconds by default) % % CopyPause - Time (in seconds) given to MS word to copy a string. % (0.3 seconds by default) % % CreateMatrix - Flag to indicate if the function needs to create the % matrix within the Microsoft Equation field. % [0 | 1(default)] % % Format - Specify the output format of the copied numeric values. % To see the description of this field in detail, check % the formatSpec section in num2str documentation. % % To set the same format to all cells of the matrix: % - formatStr % *where: % - formatStr is a valid formatSpec string. % % To specify the format for a certain range of cells: % - {rowsIndx, colsIndx, formatStr} % *where: % - rowsIndx is the index of the rows whose % format will be modified (empty for all rows). % - columnsIndx is the index of the columns whose % format will be modified (empty for all cols). % - formatStr is a valid formatSpec string. % % DecimalMarker - Single character used to notate the decimal part of % numbers. % ('.' by defalut) % % Grouping - Characters used to enclose the matrix. % * This parameter is only evaluated if CreateMatrix is % set to 1. % ['none' | '[]' (default) | '{}' | '()' | '||'] % % %************************************************************************** %Examples: %************************************************************************** % - Example 1: Copy a 4x6 matrix to a Word document % 1) Create an equation within the Word document. % MS Word menu bar -> insert -> equation % 2) Create matrix M in Matlab % M = rand(4,6); % 3) Execute in a Matlab terminal: % matrix2WordEq(M); % 4) Navigate to the Word document and select the equation box % 5) After 5 seconds (by default) the matrix will be created and the % values will get copied. % % - Example 2: Fill the values of an already existing Word Equation % matrix. % 1) Create an equation within the Word document. % MS Word menu bar -> insert -> equation % 2) Add a 3 by 3 matrix. % With the equation box selected, navigate to "Equation tools" and % add a 3x3 matrix. % 3) Execute in a Matlab terminal: % matrix2WordEq(rand(3,3), 'CreateMatrix', 0); % 4) Navigate to the Word document and select the top-left cell of % the matrix. % 5) After 5 seconds (by default) the values will start to get copied % to the matrix. % Obtain matrix size. [numRows, numCols] = size(matrixIn); % Generate options structure. options = parseOptions(numRows, numCols, varargin); % Check if matrix size below the \matrix function limits if numRows*numCols > 225 && options.createMatrix % The largest matrix that can be created through the \matrix % command offered by Microsoft word is 225 cells long % (numRows*numcols <= 255). For larger matrices the user needs to % manually create them by inserting as much rows and columns as % needed. Then, he can use matrix2WordEq function to fill it. errorMsg = 'Largest matrix that can be CREATED is 225 cells long.'; errorLine1 = 'Larger matrices must be first created manually in the Word document'; errorLine2 = '(right click over the equation matrix + add column/row).'; errorLine3 = 'Once the matrix has been manually created, run this code again with'; errorLine4 = 'the option ''CreateMatrix'' set to 0 and place the cursor on the top-left cell to fill it.'; error('Error: %s\n\n%s\n%s\n%s\n%s\n',errorMsg, errorLine1, errorLine2,... errorLine3,errorLine4); end % Intialize a COM Automation server instance with Windows script Host. try h = actxserver('WScript.Shell'); catch error('Error: Unable to initialize WScript'); end % Give the user some time to navigate to the Word document and place % the cursor on the equation field. disp(['Matlab will begin to copy the values in ',num2str(options.initPause),' seconds.']); disp('Place the cursor over the MS Equation box!'); pause(options.initPause); % Check if the user wants to create a new matrix if options.createMatrix createMatrixSpace(h, numRows, numCols, options); end % Create a cell array containing the string that will be pasted to each % cell of the matrix values = parseMatrix(matrixIn, numRows, numCols, options); % Use clipboard to copy/paste values to the Word Equation Matrix dumpValues(h, values, options.copyPause); %********************************************************************* % METHODS %********************************************************************* function dumpValues(h, values, pauseVal) %DUMPVALUES copies the formated strings stored in "values" into the %corresponding cells of a Word Equation Matrix through the clipboard. % % Input parameters: % - h: Windows Script Host handle % - values: cell array containing the strings to be copied % - pauseVal: pause between "pastes" for vID = 1:length(values) clipboard('copy',values{vID}); h.SendKeys('^{v}'); pause(pauseVal); h.SendKeys('{RIGHT}'); end end function createMatrixSpace(h, numRows, numCols, opt) %CREATEMATRIXSPACE Creates the matrix where data will be pasted. % % Input parameters: % - h: Windows Script Host handle % - numRows: number of rows of the matrix to be copied % - numCols: number of columns of the matrix to be copied % - opt: options structure if ~isempty(opt.grouping) str = [opt.grouping(1),'\matrix']; else str = '\matrix'; end clipboard('copy',str); pause(opt.copyPause) h.SendKeys('^{v}{(}','true'); pause(opt.copyPause) matrixStruct = [repmat('@',1,numRows-1),repmat('&',1,numCols-1)]; clipboard('copy',matrixStruct); pause(opt.copyPause) if ~isempty(opt.grouping) str = ['^{v}{)} {',opt.grouping(2),'} {LEFT}+{LEFT}{LEFT}{RIGHT}']; else str = '^{v}{)} +{LEFT}{LEFT}{RIGHT}'; end h.SendKeys(str,'true'); pause(opt.copyPause); end function options = parseOptions(numRows, numCols, params) %PARSEOPTIONS initializes the options structure. % % Input parameters: % - numRows: number of rows of the matrix to be copied % - numCols: number of columns of the matrix to be copied % - params: user-specified parameters % % Output parameters: % - options: options strucutre containing; % - formatsStr: cell array of strings containing the format % of each cell. % - copyPause: pause between pastes (in seconds). % - createMatrix: flag that specifies if we need to create % the matrix. % - decimalMarker: marker used to notate the decimal part. % - grouping: character used to define the grouping for the % newly created matrix. validGroupings = {'{}','()','[]','||'}; options.copyPause = 0.3; options.createMatrix = 1; options.decimalMarker = '.'; options.formatsStr = cell(numRows, numCols); options.grouping = '[]'; options.initPause = 5; errorFlag = 0; options.formatsStr = editFormat('%0.3f', numRows,... numCols, options.formatsStr); for inputID = 1:2:length(params) fieldName = params{inputID}; fieldValue = params{inputID+1}; switch lower(fieldName) case 'format' options.formatsStr = editFormat(fieldValue, numRows,... numCols, options.formatsStr); case 'initpause' if ~isnumeric(fieldValue) || fieldValue <= 0 errorFlag = 1; end options.initPause = fieldValue; case 'copypause' if ~isnumeric(fieldValue) || fieldValue <= 0 errorFlag = 1; end options.copyPause = fieldValue; case 'creatematrix' if ~isnumeric(fieldValue) || (fieldValue ~= 1 && fieldValue ~= 0) errorFlag = 1; end options.createMatrix = fieldValue; case 'decimalmarker' if ~ischar(fieldValue) errorFlag = 1; end options.decimalMarker = fieldValue; case 'grouping' if strcmpi(fieldValue,'none') options.grouping = []; elseif ~isempty(find(strcmp(fieldValue, validGroupings) == 1, 1)) options.grouping = fieldValue; else warning(['Warning: ',fieldValue, 'is not a valid grouping. Set to default']); end otherwise errorFlag = 1; end if errorFlag == 1 error(['Invalid pair key-value for field ',fieldName]); end end %****************************************************************** % Internal functions %****************************************************************** function formatsStr = editFormat(fieldValue, numRows, numCols, formatsStr) if ischar(fieldValue) formatsStr(:) = {fieldValue}; else if ~iscell(fieldValue) || length(fieldValue) ~= 3 error('Error: Invalid format'); end rowIndexs = fieldValue{1}; colIndexs = fieldValue{2}; if isempty(colIndexs) colIndexs = 1:numCols; end if isempty(rowIndexs) rowIndexs = 1:numRows; end numCols = length(colIndexs); numRows = length(rowIndexs); for rowID = 1:numRows for colID = 1:numCols formatsStr{rowIndexs(rowID), colIndexs(colID)} = fieldValue{3}; end end end end end function values = parseMatrix(matrixIn, numRows, numCols, options) %PARSEMATRIX parses the matrix to a cell array containing the %string that will be pasted to each cell of the Word matrix, %accounting for format specifications. % % Input parameters: % - matrixIn: user-defined matrix. % - numRows: number of rows of the matrix to be copied % - numCols: number of columns of the matrix to be copied % - opt: options structure values = cell(1,numRows*numCols); linealIndx = 1; for rID = 1:numRows for cID = 1:numCols format = options.formatsStr{rID, cID}; if isempty(format) values{linealIndx} = num2str(matrixIn(rID,cID)); else values{linealIndx} = num2str(matrixIn(rID,cID), format); end if options.decimalMarker ~= '.' values{linealIndx} = strrep(values{linealIndx},'.',options.decimalMarker); end linealIndx = linealIndx+1; end end end end