Code covered by the BSD License  

Highlights from
TexTab

image thumbnail

TexTab

by

 

05 Sep 2012 (Updated )

Create formatted tables and save them as a picture like png. Saving tex files is also possible.

TexTab.m
classdef TexTab < Basic.Base
   % TexTab allows you to create nicely formatted tables and export them to a picture file like PNG.
   % 
   % The picture can easily be imported to email software and word processing software like 
   % Microsoft Word or Open Office / Libre Office. Exporting to .tex files is also possible.
   %
   % Converting to picture files is only possible if the following (freely
   % available) Software is installed on your computer:
   % - Miktex (ver. 2.9 or higher) http://miktex.org/2.9/setup
   %   Some additional packages are needed for table creation, so I recommend to allow MickTex to 
   %   install additional packages and to have an internet connection when creating the first tables 
   %   or to use the complete MickTex installation.
   % - ImageMagick and Ghostscript http://www.imagemagick.org http://downloads.ghostscript.com/public/gs906w32.exe
   %
   % Creating tables is quite simple:
   % - create a TexTab object
   % - Assign the table content to the object's Data property
   % - modify further properties to format the table
   % - call the writePic or writeTex method to create the table.
   %
   % Example:
   % Data = rand(10,2);                         % Create some data
   % obj = IoFun.TexTab;                        % Create the TexTab object
   % obj.Data = [{'x','y'};num2cell(Data)];     % Assign the data including a headline
   % obj.BgColor(1,:) = {'bluem'};              % Format: Background color of the Headline is blue
   % obj.FontStyle(1,:) = {'\Large'};           % Large Font for the headline
   % [Alerts,~] = find(Data(:,2)>0.8);          % Find high data values:
   % obj.Color(Alerts+1,2) = {'red'};           % mark them with red colour
   % obj.writePic('c:\temp\test.png');          % create the table and write it to a png file
   %                                            % This uses Miktex and Imagemagick and is time 
   %                                            % consuming.
   % clear
   % a=IoFun.TexTab.png2data('c:\temp\test.png'); % Retrieve the Data from the png figure file.
   %                                            % This uses ImageMagick and is time consuming
   %
   % To merge cells in rows and columns combinedly, set your Data property like in the
   % following example:
   %    obj.Data = {'a' '<' 'c'          
   %                '^' '<' 'c'};
   %
   % To get started, check the methods example1 to example4 and watch the help of the properties 
   % and methods.
   % Call the examples:
   % obj = IoFun.TexTab;   
   % obj.example1;
   %
   % Convert underlying data from the png file to a csv txt file
   % This uses ImageMagick and is time consuming
   % IoFun.TexTab.png2csv('c:\temp\test.png','c:\temp\test.txt')  
   % 
   %    
   % (C) Alstom Transport Deutschland GmbH
   %     Salzgitter, Germany
   %     GBO2
   %     Marcel Rland
   % 
   
   properties     
      % Fontweight defines the font weight for arbitrary cells.
      % It should have the same size as the Data. 
      % The set.Data method formats Fontweight automatically.
      % If left empty, normal font weight is chosen.
      FontWeight
      
      % BgColor defines the background color for arbitrary cells.
      % It should have the same size as the Data.
      % The set.Data method formats BgColor automatically.
      % If left empty, the background color is white.
      % Use valid Tex colors like 'red', 'green', the light blue color
      % bluem or a self defined color (cf. property <ColorDef>)
      % Example
      % >> obj.BgColor
      % 
      % ans = 
      % 
      %     'bluem'    'bluem' 
      %          []    'green' 
      %          []         [] 
      %          []         [] 
      %          []         [] 
      BgColor
      
      % Color defines the text color for arbitrary cells.
      % It should have the same size as the Data.
      % The set.Data method formats Color automatically.
      % Use valid Tex colors like 'red', 'green', the light blue color
      % bluem or a self defined color (cf. property <ColorDef>)
      % If left empty, the color is black.
      Color
      
      % CellFormat defines the general format of the table as defined in the Tex tabular
      % environment.
      % It should be a string describing the cell format in the following manner:
      % For each column, use one of the letters l,r,c. For Lines between the columns pace a |
      % The following list sums up the meaning of each character in the CellFormat property:
      % |   Vertical line before/behind a cell
      % ||  Double vertical line before/behind a cell
      % l   Cell content is justified left
      % r   Cell content is justified right
      % c   Cell content is centered
      % Example:
      % |r||cc|l|
      % This formats the table with 4 columns. The first
      % column is aligned left followed by two centered columns and a left aligned column.
      % The first column has a vertical line on its left side. On its right side, there is a
      % doubled ine. Between the 2nd and the 3rd column there is no vertical line and the last
      % column has a vertical line on its right and left.
      % If CellFormat is empty, the default format is chosen: All cells are centered with single lines
      % on both sides.
      CellFormat
      
      
         % FontStyle defines font styles for arbitrary cells. 
         % Fontstyle is a cell array with the same size as the Data Property. It is automatically 
         % formatted to that size when the Data property is set. You can use any Tex font style
         % The following table shows some important font styles. A combination of font sytles
         % is possible.
         % '\bf'     Bold
         % '\rm'     Roman
         % '\tt'     Typewriter
         % '\it'     Italic
         % '\sl'     Slanted
         % '\sf'     Sans serif
         % '\tiny'   
         % '\small'
         % '\large'
         % '\Large'
         % '\LARGE'
         % '\huge'  %This is not recommended since it creates problems with
         %          %the row hight and the types stick to the upper line of the box 
         % '\Huge'  %This is not recommended since it creates problems with
         %          %the row hight and the types stick to the upper line of the box 
      FontStyle
      
      % DefaultFont can be used to define a default font, which will be used for the 
      % whole table. If left empty, the standard font will be used.
      % Currently the following fonts are tested. 
      % - 'uarial'
      % - 'helvetica'
      % Possibly there are further fonts that work. For further infomation,
      % refer to http://www.tug.dk/FontCatalogue/
      DefaultFont
      
      % ColorDef can be used to define custom RGB colors. 
      % The color definition is stored as a struct with the custom color
      % name as field name. Assign to this field a tree element vector with
      % RGB color parts expressed by numbers between 0 and 1.
      % Example:
      % obj.ColorDef.myCol = [0.91, 0.8, 0.3];   %RGB color definition
      % obj.ColorDef.myRed = [1, 0, 0];   %RGB color definition
      ColorDef
      
      % DefaultNumericalFormat Doubles generally will be converted automatically in this format
      % See the help entry of sprintf for more details
      DefaultNumericalFormat = '%5.3f'
      
      % NumericalFormat This is a cell with conversion precisions for each double value in the Data 
      % property.
      % See the help entry of sprintf for more details
      NumericalFormat
      
      % Density contains the resolution of the graphical output createt
      % with the method writePic (using the convert command of
      % ImageMagick). Low values yield in small size output files and high
      % values assure a good output resolution. 
      %Density is expressed as a string in the following manner:
      % obj.Density = '1600x1600'
      Density = '600x600'           %       DPI
      
      % UseInterpreter - If set true, mathmatical expressions will be interpretated, eg. \mu will 
      % create the  sign. Additionally numericals with the value Inf will be converted to the 
      % infinity sign and NaNs will be converted to a self-defined NaN sign. 
      UseInterpreter = true
      
      % LineStyle Choose the style of your lines
      % LineStyle is cell array with one column containing the the style of each horizontal
      % line in the column. The following line styles are allowed:
      % 'normal'
      % 'none'
      % 'thick(x)' :line with the thickness x, expessed in px
      LineStyle = []
      
      % TODO:
      % - alow dobble horizontal lines
      % - fix bug with double vertical lines and merged loumns
      % - allow bold vertical lines
      % - allow to enter font sizes
      % - line feeds in cells

   end
   properties (SetAccess = private, Hidden=true)
      % TexString contains the tex string which will be written to file
      % with the method writeTex
       TexString   
   end
   properties(Dependent=true)
      % Data cell array containing the data as string or double.
      % Strings may contain Latex formats also.
      % The LATEX package colortbl is loaded automatically.
      % Example:
      %   obj.Data = {'a' 'b' 'c' 'd'; 1 2 '<' pi;'a' '\textcolor{green}{b}' 'c' '\colorbox{red}{d}'}
      %
      % Data is dependent and shadowed by PrivateData in order to have access to other
      % Properties like FontWeight from the set.Data method
      Data
   end
   properties (Access=private)
      PrivateData %Shadows the Data property.
   end
   methods
      function obj = TexTab(varargin)
         % Creates a TextTab object and checks, if third party software (ImageMagick and Miktex)
         % is installed and accessible. Note that the correct installation
         % of Ghostscript is noch checked. If you have any strange
         % behaviour, check your Ghostscript istallation.
         % Refer to the help entries of this class for more information.
         [stat,~]=dos('texi2dvi -?');
         if stat
            obj.error('Zeisig:IoFun:TexTab:texi2dviNotFound');
         end
         [stat,~] = dos('dvips -?');
         if stat
            obj.error('Zeisig:IoFun:TexTab:dvipsNotFound');
         end
         [stat,~] = dos('convert -version');
         if stat
            obj.error('Zeisig:IoFun:TexTab:convertNotFound');
         end
         [stat,~] = dos('identify -version');
         if stat
            obj.error('Zeisig:IoFun:TexTab:identifyNotFound');
         end
      end
      function example1(obj)
         % Create your own table based on this example
         % Creating a table can be done in the following manner:
         % * create the object
         % * write the data to the object's Data property
         %   Use the following charaters to merge cells:
         %   - < (merge horizontally)
         %   - ^ (merge vertically)
         % * format the table by setting additional properties like:
         %      - ColorDef
         %      - BgColor
         %      - CellFormat
         %      - NumericalFormat
         %      - FontStyle

         obj.Data = {'a' 'b' '<' '<';                      % First line: merge the last 3 cells 
                      1   2  '<' pi;                       % Second line: merge the second and the third line
                     'a' '\textcolor{green}{b}' 'c' 'd'};  % Use a tex command to set the second 
                                                           % value's color to green
         obj.ColorDef.blu   = [0.1, 0.8, 0.95];   %RGB color definition: This color will be used in the following line
         obj.BgColor(1,:) = {'blu'};
         obj.ColorDef.myCol = [0.91, 0.8, 0.3];   %RGB color definition: This color will be used in the following line
         obj.Color(3,1) = {'myCol'};
         obj.Color(3,3)   = {'red'};              %Use a predefined tex color
         obj.writeTex('c:\temp\ex1.tex');         %Convert to tex (Optional)
         obj.writePic('c:\temp\ex1.png');         %Convert to a png picture.
         clear
         Data = IoFun.TexTab.png2data('c:\temp\ex1.png');         %Retrieve the data from a png picture file
         disp(Data);
         IoFun.TexTab.png2csv('c:\temp\ex1.png','c:\temp\ex1.csv');    %wirite the picture's data to a csv file         
      end
      function example2(obj)
         % Create your own table based on this example
         % Creating a table can be done in the following manner:
         % * create the object
         % * write the data to the object's Data property
         %   Use the following charaters to merge cells:
         %   - < (merge horizontally)
         %   - ^ (merge vertically)
         % * format the table by setting additional properties like:
         %      - ColorDef
         %      - BgColor
         %      - CellFormat
         %      - NumericalFormat
         %      - FontStyle
         data = rand(10,4);
         [xmin,ymin] = find(data==min(min(data)));
         Header1 = {'Messwerte' '<' '<' '<' '<'};
         Header2 = {'n' 'x1' 'x2' '<' 'x3'};
         Header3 = {'^' '^'  'a'  'b' '^'};
         FirstCol = num2cell([1:10]'); %#ok<*NBRAK>
         FirstCol(3:4) = {'^'};
         FirstCol(6:8) = {'^'};
         nHeader = 3;
         nLeftCols = 1;
         obj.Data = [Header1; Header2; Header3; FirstCol num2cell(data)];
         obj.ColorDef.lightRed   = [1 0.8 0.8];   %RGB color definition: This color will be used in the following line
         obj.ColorDef.darkRed    = [0.8 0.2 0]; 
         obj.ColorDef.lightGreen = [0.8 1 0.8];
         obj.ColorDef.darkGreen  = [0 0.6 0];
         obj.Data{5,2} = inf;
         obj.BgColor(5,2) = {'lightRed'};
         obj.Color(5,2) = {'red'};
         obj.DefaultFont = 'uarial';
         obj.CellFormat = '|l||c|c|c|r|';              %This line is optional, you can ommit it to use a default format
         obj.NumericalFormat(:,1)={'%u'};
         obj.NumericalFormat(:,3)={'%7.5f'};
         obj.FontStyle(xmin+nHeader,ymin) = {'\bf'};
         obj.Color(xmin+nHeader,ymin+nLeftCols) = {'darkGreen'};
         obj.BgColor(xmin+nHeader,ymin+nLeftCols) = {'lightGreen'};
         obj.FontStyle(1,:) = {'\Large'};
         obj.FontStyle(2,:) = {'\bf'};
         obj.BgColor(1,1) = {'bluem'};
%          obj.writeTex('c:\temp\ex2.tex');
         obj.writePic('c:\temp\ex2.png');
      end
      function example3(obj)
         % Create your own table based on this example
         % Creating a table can be done in the following manner:
         % * create the object
         % * write the data to the object's Data property
         %   Use the following charaters to merge cells:
         %   - < (merge horizontally)
         %   - ^ (merge vertically)
         % * format the table by setting additional properties like:
         %      - ColorDef
         %      - BgColor
         %      - CellFormat
         %      - NumericalFormat
         %      - FontStyle

         data = [ 0.6228    0.7449    0.1629    0.2296
                   0.7966    0.8923    0.8384    0.9361
                   0.7459    0.2426    0.1676    0.6832
                   0.1255    0.1296    0.5022    0.9621
                   0.8224    0.2251    0.9993    0.4380
                   0.0252    0.3500    0.3554    0.9403
                   0.4144    0.2871    0.0471    0.0058
                   0.7314    0.9275    0.2137    0.6103
                   0.7814    0.0513    0.3978    0.8011
                   0.3673    0.5927    0.3337    0.2330
                   0.9325    0.2905    0.3991    0.7425
                   0.7633    0.4026    0.5994    0.7579
                   0.8264    0.8621    0.8005    0.3891
                   0.5735    0.6147    0.1051    0.4293
                   0.7926    0.9912    0.8214    0.9563
                   0.3290    0.2037    0.8411    0.5730
                   0.2235    0.8272    0.3545    0.8497
                   0.3124    0.6759    0.4301    0.2763
                   0.5845    0.2489    0.5722    0.6223
                   0.8299    0.4758    0.7008    0.5884
                   0.9635    0.6198    0.1590    0.9852
                   0.0859    0.2606    0.2369    0.5595
                   0.5005    0.4457    0.7022    0.9336
                   0.5216    0.8440    0.3755    0.7203
                   0.0902    0.1962    0.9737    0.4840
                   0.9047    0.3039    0.9723    0.6390
                   0.8844    0.4833    0.6437    0.8876
                   0.4390    0.3378    0.8601    0.1987
                   0.7817    0.7985    0.4019    0.3954
                   0.1485    0.9875    0.6319    0.9922];
%          [xmin,ymin] = find(data==min(min(data)));
         Header1 = {'Messwerte' '<' '<' '<'};
         Header2 = {'x_1' '<' 'x3' 'x4'};
         obj.Data = [Header1; Header2;num2cell(data)];
         obj.FontStyle(1,:) = {'\Large'};
         obj.FontStyle(2,:) = {'\bf'};
         obj.BgColor(1,:) = {'bluem'};         
         obj.writePic('c:\temp\ex3.png');

      end
      function example4(obj)
         % Create your own table based on this example
         % This example shows how to use different line styles and merge cells in rows and
         % columns
            obj.Data = {'Title' '<' '<' '<' '<'
                        'Subtitle' '<' '<' '<' '<'
                        'a' '<' 'c' 'd' '<'
                        '^' '<' 'c' 'd' 'e'
                        'a' 'b' 'c' 'd' 'e'
                        'a' 'b' 'c' 'd' 'e'};
            obj.LineStyle{2} = 'thick(2)';
            obj.LineStyle{1} = 'none';
            obj.writePic('c:\temp\ex4.png');
      end
      
      function obj = set.Data(obj,Data)
         % Automatically initializes other properties
         % The data iself is stored in the PrivateData property.
         if isnumeric(Data)
%             warning('Zeisig:IoFun:TexTab:ConvertingDataToCell','Converting Data to cell.');
             Data = num2cell(Data);
         end
         obj.PrivateData = Data;
         obj.FontWeight  = cell(size(Data));
         obj.FontStyle   = cell(size(Data));
         obj.LineStyle   = repmat({'normal'},size(obj.Data,1),1);
         obj.BgColor     = cell(size(Data));
         obj.Color       = cell(size(Data));
         obj.NumericalFormat = repmat({obj.DefaultNumericalFormat},size(Data));
         n = size(obj.Data,2);
         if isempty(obj.CellFormat)
            obj.CellFormat = [repmat('|c',1,n) '|'];
         end
      end
      function Data = get.Data(obj)
         Data = obj.PrivateData;
      end
      function obj = set.ColorDef(obj,ColorDef)
         % Perform some input checks
         FN = fieldnames(ColorDef);
         for i = FN'
            if ~isnumeric(ColorDef.(char(i)))
               obj.error('Zeisig:IoFun:TexTab:ColorDefNotNumeric');
            end
            if any(size(ColorDef.(char(i)))~=[1,3])
               obj.error('Zeisig:IoFun:TexTab:ColorDefWrongSize');
            end
            if any (ColorDef.(char(i))>1)
               obj.error('Zeisig:IoFun:TexTab:ColorDefValuesToohigh');
            end
            obj.ColorDef = ColorDef;
         end
      end
      function writeTex(obj,filename)
         % obj.writeTex(filename)
         % Writes a .tex file expressing the table specified by obj.
         % Specify the filename by it's full path.
          
          %Calls obj.update to write a .tex file to disk
         obj.update;
         [fid] = fopen(filename,'w+');
         if fid == -1
            error('Could not open file.');
         end
         fprintf(fid,'%c',obj.TexString);
         fclose(fid);
         disp(filename);
      end
      function writePic(obj,filename)
         % Creates a picture file of the TexTab object.
         % automatically updates the object, creates some temp files in c:\temp,
         % converts them to a png file and deletes the temporary files.
         % This method uses the following external software, which are called with the dos command:
         %  * texi2dvi
         %  * dvips
         %  * convert
         % So make sure you have them installed (MikTex and ImageMagick with correct installation of 
         % Ghostscript). Additionally Windows' path must be set correctly
         % to the corresponding binary directories.
         % Usage:
         %  obj.writePic(filename)
         %  The picture format is chosen according to the filename. The following formats are
         %  possible:
         %   * png
         %   * jpg
         %   * gif
         %
         % If you write a .png file, the pure data is written to the png file as a Property
         % (Key: MyMetaData)
         % You can read this metadata in a dos shell with the following command (using ImageMagick):
         % identify -verbose test.png
         % Or you can use the free tool TweakPNG.
         % Use the following static methods to acces the data directly in Matlab or convert it to a csv file.
         %
         % See also:
         % png2data
         % png2csv
         
         obj.update;
         [~,TempDir]=dos('echo %temp%');        %Get the temp directory specified by Windows
         TempDir(TempDir==char(10))=[];
         obj.writeTex(fullfile(TempDir,'tmp.tex'));
         if nargin<2
            filename = 'tab.png';
         end
         wd = pwd;
         disp('Converting to PNG. This may be time consuming.');
         try %#ok<TRYNC>
            cd (TempDir);
            disp('...Creating temporary dvi file.');
            [stat,Res] = dos('texi2dvi -q tmp.tex');
            if stat
               disp(Res);
            end
            disp('...Creating temporary ps file.');
            [stat,Res] = dos('dvips -q -E tmp.dvi');
            if stat
               disp(Res);
            end
            % [stat,Res] = dos(sprintf('convert -density %s tmp.ps %s',obj.Density,filename));
            
            % Prepare Meta data to be stored in png file
            % Desired format is a single csv string
            nums = cellfun(@isnumeric,obj.Data);
            Data = obj.Data;
            Data_ = Data;
            Data_(~nums)=cell(size(find(~nums)));
            Data_ = cellfun(@num2str,Data_,'uniformoutput',false);
            Data(nums) = Data_(nums);
            [r,c] = size(Data);
            seps = repmat({','},size(Data));
            seps(:,end) = repmat({';'},r,1);
            
            MetaData = cell(r,2*c);
            MetaData(:,1:2:2*c-1) = Data;
            MetaData(:,2:2:2*c) = seps;
            MetaData = cell2str(MetaData);
            MetaData(MetaData==10) = [];
            
            disp('...Converting temporary ps file to desired picture file.');
            [stat,Res] = dos(sprintf('convert -density %s -units PixelsPerInch -set MyMetaData "%s" tmp.ps %s',obj.Density,MetaData,filename));
            if stat                                   %-units PixelsPerInch: Hint of M. Stiepel to get a correct picture size in the exif data
               disp(Res);
            end
            disp('...Deleting temporary files.');
            [stat,Res] = dos('del tmp.tex');
            if stat
               disp(Res);
            end
            [stat,Res] = dos('del tmp.dvi');
            if stat
               disp(Res);
            end
            [stat,Res] = dos('del tmp.log');
            if stat
               disp(Res);
            end
            [stat,Res] = dos('del tmp.aux');
            if stat
               disp(Res);
            end
            [stat,Res] = dos('del tmp.ps');
            if stat
               disp(Res);
            end
         end
         disp(filename);
         cd(wd);
      end
   end
   methods (Access = private)
      function obj = update(obj)
         % This method updates the object to the correct value of obj.TexStr
         % It parses obj.Data and all format properties to a valid tex strring.
         if strcmp(obj.Data(:,1),'<')
            obj.error('Zeisig:IoFun:TexTab:ArrowInFirstColumn');
         end
         if isempty(obj.LineStyle)
            obj.LineStyle = repmat({'normal'},size(obj.Data,1),1);
         end
         for Prop = {'FontWeight','BgColor','FontStyle','NumericalFormat','Color'}
            if any(size(obj.(char(Prop)))>size(obj.Data))
               obj.error('Zeisig:IoFun:TexTab:PropertyTableExceedsSize',char(Prop))
            end
         end
         cr = char(10);
         Colorstr = [cr '\definecolor{bluem}{rgb}{0.7,0.8,0.95}' cr];
         if ~isempty(obj.ColorDef)
             colors = fieldnames(obj.ColorDef);
             for i = 1:length(colors)
                 CurrColName = colors{i};
                 CurrColVal  = obj.ColorDef.(colors{i});
                 CurrColStr  = sprintf('%4.2f,%4.2f,%4.2f',CurrColVal(:));
                 Colorstr = sprintf('%s\\definecolor{%s}{rgb}{%s}\n',...
                            Colorstr,...
                            CurrColName,...
                            CurrColStr);
             end
         end
         if ~isempty(obj.DefaultFont)
            switch lower(obj.DefaultFont)
               case 'uarial'  %Near to arial (No Math Support)
                DefFontStr = sprintf('%s{%s}\n%s\n%s','\usepackage[scaled]',...
                                          obj.DefaultFont,...
                                           '\renewcommand*\familydefault{\sfdefault}',...
                                           '\usepackage[T1]{fontenc}');
               case {'arev','cmbright'}    %arev (Math Support)
                 DefFontStr = sprintf('%s{%s}\n\n%s','\usepackage',...
                                          obj.DefaultFont,...
                                           '\usepackage[T1]{fontenc}');
               otherwise
                  DefFontStr = sprintf('%s{%s}\n%s\n%s','\usepackage[scaled]',...
                                          obj.DefaultFont,...
                                           '\renewcommand*\familydefault{\sfdefault}',...
                                           '\usepackage[T1]{fontenc}');
            end
         else
             DefFontStr = '';
         end
         TabFormat = sprintf('\\begin{tabular}{%s}',obj.CellFormat);
         Header = ['\documentclass{article}' cr ...
                  '\usepackage{colortbl}' cr ...
                  '\usepackage{multirow}' cr ...
                  '\usepackage{array}' cr ...
                  '\usepackage{tabularx}' cr ...
                  '\makeatletter' cr ...                 %Thanks to http://tex.stackexchange.com/questions/3445/latex-tables-how-do-i-make-bold-horizontal-lines-typically-hline
                  '\def\hlinewd#1{%' cr ...
                  '\noalign{\ifnum0=`}\fi\hrule \@height #1 %' cr ...
                  '\futurelet\reserved@a\@xhline}' cr ...
                  '\makeatother' cr ...
                  DefFontStr ...
                  Colorstr ...
                  '\begin{document}' cr ...
                  '\pagestyle{empty}' cr ...
                  '{' cr ...
                  '\setlength{\extrarowheight}{3pt}' cr...    %Package array; to correct row hight, when \hline is used, cf.http://nepsweb.co.uk/docs/tableTricks.pdf
                  TabFormat cr ...
                  '\hline' cr];
         Footer = [cr '\end{tabular}' cr ...
                   '}' cr ...
                   '\end{document}' cr];
         
         PreTable = obj.Data;
         
        
         %Convert numerical data
         id = find(cellfun(@isnumeric,PreTable));
         if ~isempty(id)
            for i = id'
               PreTable{i} = num2str(PreTable{i},obj.NumericalFormat{i});
            end
         end
         if obj.UseInterpreter
            PreTable = regexprep(PreTable,'Inf','\\infty');
            PreTable = regexprep(PreTable,'NaN','\\o');
         end
         
         %Convert escape characters
         if obj.UseInterpreter
            PreTable = regexprep(PreTable,'(.*_.*|.*\\.*)','\$$1\$');
         else
             PreTable = regexprep(PreTable,'_','\\_');
         end
         PreTable = regexprep(PreTable,'','{\\ss}');
         PreTable = regexprep(PreTable,'','\\"u');
         PreTable = regexprep(PreTable,'','\\"U');
         PreTable = regexprep(PreTable,'','\\"o');
         PreTable = regexprep(PreTable,'','\\"O');
         PreTable = regexprep(PreTable,'','\\"a');
         PreTable = regexprep(PreTable,'','\\"A');
         
         %Bold cells
         if ~isempty(obj.FontWeight)
            [idx,idy] = find(~cellfun(@isempty,obj.FontWeight));
            for i = 1:length(idx)
               PreTable{idx(i),idy(i)} = ['\textbf{' PreTable{idx(i),idy(i)} '}'];
            end
         end
         
         %FontStyles
         if ~isempty(obj.FontStyle)
            [idx,idy] = find(~cellfun(@isempty,obj.FontStyle));
            for i = 1:length(idx)
               PreTable{idx(i),idy(i)} = [obj.FontStyle{idx(i),idy(i)} ' ' PreTable{idx(i),idy(i)}];
            end
         end

         %Background Color
         if ~isempty(obj.BgColor)
            [idx,idy] = find(~cellfun(@isempty,obj.BgColor));
            for i = 1:length(idx)
               PreTable{idx(i),idy(i)} = sprintf('\\cellcolor{%s}{%s}',obj.BgColor{idx(i),idy(i)}, PreTable{idx(i),idy(i)});
            end
         end         

         %Text Color
         if ~isempty(obj.Color)
            [idx,idy] = find(~cellfun(@isempty,obj.Color));
            for i = 1:length(idx)
               PreTable{idx(i),idy(i)} = sprintf('\\color{%s}{%s}',obj.Color{idx(i),idy(i)}, PreTable{idx(i),idy(i)});
            end
         end

         %% Merge cells in a row
         additionalCellsWithoutSublines = cell(size(obj.Data));
         [idRow,idCol] = find(~cellfun(@isempty,regexp(PreTable,'<')));   %find mergable cells
         if ~isempty(idRow)
            [~,id] = sort(idRow,1,'ascend');   %Columns should be contiguous
            idRow = idRow(id);
            idCol = idCol(id);
          id = [find(diff([idCol(1);idCol])~=1)];   %Vector with first ids of '<' cells
          n = diff([id; length(idCol)+1]) + 1;      %Vector with corresponding number of contiguous '<' cells
          
%           CellJust=regexp(obj.CellFormat,'\|*','split');    %Justification string ('c','l','r')
%           CellJust(cellfun(@isempty,CellJust))=[];
%           if length(CellJust)~=size(obj.Data,2);
%              CellJust = repmat({'c'},1,size(obj.Data,2));
%           end
          CellJust = regexprep(obj.CellFormat,'\|','');
          CellVertBars = regexp(obj.CellFormat,'[clr]','split');
%           j = 1;
          for i = 1:length(id)
             CellContent = PreTable{idRow(id(i)),idCol(id(i))-1};
             if   idRow(id(i))+1<=size(PreTable,1) &&...
                  strcmp(PreTable{idRow(id(i))+1,idCol(id(i))-1},'^')         %cell left down containes a ^ => Nested \multicolumn, \multirow
               vertVec = PreTable(idRow(id(i))+1:end,idCol(id(i))-1);
               if ~any(strcmp(PreTable{idRow(id(i)),idCol(id(i))-1},{'^' '<'}))
                  idvertMerge = find(strcmp(vertVec,'^'));
                  nRows  = 2;                                                    %Start searching in the second line
                  if length(idvertMerge)>1
                     delta = 1;
                     while delta==1 
                        if nRows<=length(idvertMerge)
                           delta = idvertMerge(nRows)-idvertMerge(nRows-1);
                        else
                           delta = 0;
                        end
                        nRows = nRows + 1;
                     end
                     nRows = nRows - 1;
                  end
                  
%                   fprintf('%u...%u\n',i,nRows);
                  CellContent = sprintf('\\multirow{%u}{*}{%s}',...
                     nRows, ...
                     CellContent);
               end
               if isempty(additionalCellsWithoutSublines{idRow(id(i))})
                  j = 1;
                  additionalCellsWithoutSublines{idRow(id(i)),j} = [idCol(id(i))-1:idCol(id(i))+n(i)-2];
               else
                  j = j + 1;
                  additionalCellsWithoutSublines{idRow(id(i)),j} = [idCol(id(i))-1:idCol(id(i))+n(i)-2];
%                   LastadditionalRow = idRow(id(i));
               end
             else
             end
             if idCol(id(i))==2    %The multiple cell is in the first column
                PreTable{idRow(id(i)),idCol(id(i))-1} = sprintf('\\multicolumn{%u}{%s%s%s}{%s}',...
                                                                  n(i), ...
                                                                  CellVertBars{idCol(id(i))-1}, ...
                                                                  CellJust(idCol(id(i))-1), ...
                                                                  CellVertBars{idCol(id(i))+n(i)-1}, ...
                                                                  CellContent);
             else
                PreTable{idRow(id(i)),idCol(id(i))-1} = sprintf('\\multicolumn{%u}{%s%s}{%s}',...
                                                                  n(i), ...
                                                                  CellJust(idCol(id(i))-1), ...
                                                                  CellVertBars{idCol(id(i))+n(i)-1}, ...
                                                                  CellContent);
             end
          end
          
         end
         idRowMultiCol = idRow;
         idColMultiCol = idCol;
         PreTable = regexprep(PreTable,'(?<=\{)\^(?=\})','');
         %% Merge cells in a column
         [idRow,idCol] = find(~cellfun(@isempty,regexp(PreTable,'\^')));   %find mergable cells
         [~,id] = sort(idCol,1,'ascend');   %Columns should be contiguous
         idRow = idRow(id);
         idCol = idCol(id);
         id = [find(diff([1;idRow])>1);find(diff([1;idCol])>0)];   %Vector with first ids of '^' cells
         id = unique(id);
        n=zeros(length(idRow),1);
        n(1) = 2;
        j = 1;
        for i = 2:length(idRow)
            if (idCol(i)==idCol(i-1))&& ((idRow(i)-idRow(i-1))==1)
               n(j) = n(j)+1;
            else
               j = j+1;
               n(j) = 2;
            end
        end
        n(j+1:end) = [];
         for i = 1:length(id)
           PreTable{idRow(id(i))-1,idCol(id(i))} = sprintf('\\multirow{%u}{*}{%s}',...
                                                            n(i), ...
                                                            PreTable{idRow(id(i))-1,idCol(id(i))});
        end
        PreTable = regexprep(PreTable,'\^','');
        idRowMultiLine = idRow;
        idColMultiLine = idCol;

         PreTable = [cellfunMr(@horzcat,PreTable(:,[1:end-1]),'&') PreTable(:,end)];    %Toolbox.Alstom
         PreTable(cellfun(@isempty,PreTable))={'&'};
         for i = 1:length(idRowMultiCol)
            PreTable{idRowMultiCol(i),idColMultiCol(i)} = ''; %Remove the & for the multicolumn
         end
         for i = 1:size(PreTable,1)
            if any(i==idRowMultiLine-1)||~isempty(additionalCellsWithoutSublines{i})
               j = i==idRowMultiLine-1;
               ColWithoutSubLine = [[idColMultiLine(j)]' additionalCellsWithoutSublines{i,:}];
               ColWithSubLine = 1:size(obj.Data,2);
               ColWithSubLine(ColWithoutSubLine) = [];
               clear ClineCommand;
               ClineCommand = cell(1,length(ColWithSubLine));
               ClineCommand{1} = '\\';
               for k = 1:length(ColWithSubLine)
                  ClineCommand{k+1} = sprintf(' \\cline{%u-%u}',ColWithSubLine(k),ColWithSubLine(k));
               end
               PreTable(i,size(obj.Data,2)+1) = {cell2str(ClineCommand)}; %{sprintf('\\\\ \\cline{%u-%u}',idColMultiLine(j)+1,size(obj.Data,2))};
            else
               switch regexp(obj.LineStyle{i},'[^\(\)\d]*','match','once')
                  case 'normal'
                     PreTable(i,size(obj.Data,2)+1) = {'\\ \hline'};
                  case 'none'
                     PreTable(i,size(obj.Data,2)+1) = {'\\'};
                  case 'thick'
                     Thickness = regexp(obj.LineStyle{i},'(?<=\()\d*(?=)','match','once');
                     PreTable(i,size(obj.Data,2)+1) = {sprintf('\\\\ \\hlinewd{%spt}',Thickness)};
                  otherwise
                     disp('Warning: assumed normal linestyle.');
               end
            end
         end
         
         %Convert to string and add header and footer
         Table = cell2str(PreTable);
         Table = regexprep(Table,'&(?=\\\\ \\hline)','');  %Remove Remaining cell breaks at the end of a line (Remaining due to the multicolumn algorithm)
         Table = regexprep(Table,'&(?=\\\\ \\cline)','');  %Remove Remaining cell breaks at the end of a line (Remaining due to the multicolumn algorithm)
         Table = regexprep(Table,'&(?=\\\\)','');  %Remove Remaining cell breaks at the end of a line (Remaining due to the multicolumn algorithm)
%          Table = regexprep(Table,char(10),['\\\\\\hline' cr]);
         obj.TexString = [Header Table Footer];
      end 
   end
   methods (Static=true)
      function [Data_,CsvData] = png2data(Filename)
         % [Data_,CsvData] = png2data(Filename);
         % Gets TexTab metadata from a .png file created by this class.
         % Data is a cell array
         % CsvData is a string with csv data, which can be written directly to a csv file.
         %
         % See also:
         % png2csv
         [~,~,ext] = fileparts(Filename);
         if ~strcmpi(ext,'.png')
            warning('Zeisig:IoFun:TexTab:MetadataOnlyForPng','Metadata is supported only for .png files.');
         else
            Command = sprintf('identify -verbose %s',Filename);
            [~,PngInfo] = dos(Command);
            Data = regexp(PngInfo,['(?<=MyMetaData:\s)[^' char([10 13]) ']*'],'match','once');
            if isempty(Data)
               warning('Zeisig:IoFun:TexTab:NoMetadata','No Metadata found.');
            else
               CsvData = regexprep(Data,';',char(10));
               
               Lines = regexp(Data, ';','split');
               Cells = regexp(Lines(1:end-1),',','split');
               Data_ = reshape([Cells{:}],length(Cells),length(Cells{1}));
               Data_ = Data_';
            end
         end
      end
      function png2csv(Source,Dest)
         % png2csv(Source,Dest)
         % Gets TexTab metadata from a .png file created by this class and writes a csv file
         % containing this metadata.
         % Source ist the png file
         % Dest is the csv file.
         %
         % See also:
         % png2data
          [~,Data] = IoFun.TexTab.png2data(Source);
          fid = fopen(Dest,'w+');
          if fid==-1
             error('Could not create CSV file. Try to close all programms which have might have opened the file.');
          end
          fprintf(fid,'%c',Data);
          fclose(fid);
      end
   end
end

function ResCell = cellfunMr(fname,C,D,varargin)
%function ResCell = cellfunMr(fname,C,D,varargin)
%Is the same as Matlab's buid-in cellfun function, but
%it accepts scalar values for the input parameter D or C.
%
%See also:
%cellfun
if ~iscell(D) 
   D = {D};
elseif ~iscell(C) 
   C = {C};
end
if length(D)== 1
   D= repmat(D,size(C));
elseif length(C) == 1
   C = repmat(C,size(D));
end
try
   ResCell = cellfun(fname,C,D);
catch ME
   if strcmp(ME.identifier,'MATLAB:cellfun:NotAScalarOutput')
      ResCell = cellfun(fname,C,D,'uniformoutput',false);
   end
end
end
function str = cell2str(cell)
% function str = cell2str(cell)
% Creates a string from a cell string. Each line of the str is finished with a char(10).
cr = char(10);
str = '';
for i = 1:size(cell,1)
   str = [str cr cell{i,:}]; %#ok<AGROW> %This function is not intended for huge cells
end
str(1)=[];
end

Contact us