gusucode.com > datatypes 工具箱matlab源码程序 > datatypes/@tabular/variableEditorSetDataCode.m

    function [str,msg] = variableEditorSetDataCode(a,varname,row,col,rhs)
% This function is for internal use only and will change in a
% future release.  Do not use this function.

% Generate MATLAB command to edit the content of a cell to the specified
% rhs.

%   Copyright 2011-2016 The MathWorks, Inc.

msg = '';
str = '';

[colNames,varIndices,colClasses] = variableEditorColumnNames(a);

if isdatetime(a.rowDim.labels) || isduration(a.rowDim.labels)
    % colNames, varIndices and colClasses include the rownames, if they are
    % datetimes or duration.  These aren't needed for the setData function.
    colNames(1) = [];
    varIndices(1) = [];
    varIndices = varIndices-1;
    colClasses(1) = [];
    % col also includes the time column, so decrement it
    col = col-1;
end

if length(row) > 1
    row = row(1);
end

singleCell = (length(col) == 1);
if length(col) > 1
    col = col(1);
end

if col>varIndices(end)
    msg = getString(message('MATLAB:table:VarEditorIndexOverflow'));
    col = varIndices(end);
end

% Find the left hand column of the table variable that contains col
j = find(varIndices>=col+1,1,'first')-1;

if ~isempty(j)
    colname = colNames{j};
    vardata = a.data{j};
    isGroupColumn = varIndices(j+1)>varIndices(j)+1;
    isCatColumn = isa(vardata,'categorical');
    emptyRHS = isempty(rhs);
    if isCatColumn
        % If the new categorical is just an empty string (''), set it to
        % <undefined>
        if strcmp(rhs, '')
            rhs = '<undefined>';
        end

        % Wrap the RHS string in quotes so that it appears as a string literal
        % in the generated code. Double any quotes in the RHS string so they act
        % as single quotes when rhs is itself put between quotes.
        rhs = ['''' strrep(rhs,'''','''''') ''''];
    elseif isa(vardata, 'string')
        newline = char(10);
        if ~isempty(strfind(rhs, newline))
            rhs = ['[''' strrep(rhs, newline, ''' char(10) ''') ''']'];
        else
            % Replace any pairs of single quotes (leaving single quotes
            % alone for now) with a single quote
            rhs = regexprep(rhs(2:length(rhs)-1), '''''', '''');
            % Then double all the single quotes.  This way we should have
            % valid MATLAB syntax
            rhs = ['''' strrep(rhs, '''', '''''') ''''];
        end
    end
    
    % If rhs is empty the evalin will error out with a 
    % "One or more output arguments not assigned" error which is not in
    % context for the user. Prevent this by replacing empty by the
    % appropriate empty designation.
    if isempty(rhs)
        if strcmp(colClasses{j},'cell')
            rhs = '{}';
        elseif strcmp(colClasses{j}, 'double') || ...
                strncmp(colClasses{j}, 'uint', 4) || ...
                strncmp(colClasses{j}, 'int', 3)
            rhs = '0';
        else
            rhs = '[]';
        end
    end
    rhsValue = evalin('caller',rhs);
    
    % Generate code only when rhs is a new value. This avoids cluttering the
    % command window when the table element would not change. Upstream code
    % catches a rhs that is literally the same, here we catch cases where it is
    % an expression that evaluates to the same value.
        
    % If this is a grouped column, an additional numeric sub-index is needed
    % to define which column within the table is being edited. A char matrix
    % is treated as one column, not as grouped columns.
    if isGroupColumn
        relcol = col-varIndices(j)+1;
        if iscell(vardata) % e.g. x.BloodPressure{10,2} = rhs;
            % Generate code only if the new value is different
            subsrefStruct = struct('type',{'.','{}'},'subs',{colname,{row,relcol}});
            if emptyRHS && ~singleCell
                % can't assign mutiple values to some table variable types
                % with a single value, so build a command with multiple
                % empties:  t.column(1,:) = {{},{}};
                str = [varname '.' colname '(' num2str(row) ',:) = {'];
                numEmpties = varIndices(j+1) - varIndices(j);
                for i=1:numEmpties
                    str = [str '{},']; %#ok<AGROW>
                end
                str = [str(1:length(str)-1) '};'];
            elseif row>size(a,1) || ~isequal(subsref(a,subsrefStruct),rhsValue)
                str = [varname '.' colname '{' num2str(row) ',' num2str(relcol) '} = ' rhs ';'];
            end
        else % e.g. x.BloodPressure(10,2) = rhs;
            if isa(vardata, 'categorical') || isa(vardata, 'string')
                % Already enforced that rhsValue is a string for a categorical var
            elseif ~isscalar(rhsValue)
                if isempty(rhsValue)
                    error(message('MATLAB:datatypes:InvalidValue', colname));
                else
                    error(message('MATLAB:subsassignnumelmismatch'));
                end
            end
            % Generate code only if the new value is different
            subsrefStruct = struct('type',{'.','()'},'subs',{colname,{row,relcol}});
            if emptyRHS && ~singleCell
                str = [varname '.' colname '(' num2str(row) ',:) = ' rhs ';'];
            elseif row>size(a,1) || ~isequal(subsref(a,subsrefStruct),rhsValue)
                str = [varname '.' colname '(' num2str(row) ',' num2str(relcol) ') = ' rhs ';'];
            end
        end
    else
        if iscell(vardata) % e.g. x.Weight{10} = rhs;
            % Generate code only if the new value is different
            subsrefStruct = struct('type',{'.','{}'},'subs',{colname,{row}});
            if row>size(a,1) || ~isequal(subsref(a,subsrefStruct),rhsValue)
                if size(a,1)==1 && row>1 % force the var to grow vertically
                    str = [varname '.' colname '{' num2str(row) ',1} = ' rhs ';'];
                else
                    str = [varname '.' colname '{' num2str(row) '} = ' rhs ';'];
                end
            end
        elseif strcmp('char',colClasses{j})
            % Need to get all the content of the value at the specified row
            % of the character array in order to compare against the new
            % value.
            if isempty(rhsValue)
                error(message('MATLAB:datatypes:InvalidValue', colname));
            else
                [~, columns] = size(subsref(a, struct('type',{'.'},'subs',{colname})));
                if columns == 1
                    subsrefStruct = struct('type',{'.','()'},'subs',{colname,{row, 1}});
                else
                    subsrefStruct = struct('type',{'.','()'},'subs',{colname,{row, [1, columns]}});
                end
                if row>size(a,1) || ~isequal(subsref(a,subsrefStruct),rhsValue)
                    str =  [varname '.' colname '(' num2str(row) ',1:' num2str(length(rhsValue)) ') = ' rhs ';'];
                end
            end
        elseif strcmp('datetime', colClasses{j})
            rhs = strtrim(rhs);
            if ismember(lower(rhs),{'''now''' '''yesterday''' '''today''' '''tomorrow'''}) || ...
                ismember(lower(rhs),{'now' 'yesterday' 'today' 'tomorrow'})
                % Allow keyword entry like the datetime constructor does
                str = [varname '.' colname '(' num2str(row) ') = datetime(' rhs ');'];
            elseif isempty(rhsValue)
                error(message('MATLAB:datatypes:InvalidValue', colname));
            else
                subsrefStruct = struct('type',{'.','()'},'subs',{colname,{row}});

                % Verify this is a valid datetime, with the format of the
                % current datetime array.  If it is, assign using the
                % string - the datetime constructor will use the current
                % format by default.
                dt = subsref(a,subsrefStruct);
                try
                    eval(['datetime(' rhs ', ''Format'', ''' strrep(dt.Format, '''', '''''') ''');']);
                    if row>size(a,1) || ~isequal(char(dt),rhsValue)
                        str =  [varname '.' colname '(' num2str(row) ') = ' rhs ';'];
                    end
                catch
                    error(message('MATLAB:datetime:InvalidFromVE'));
                end
            end
        else % e.g. x.Weight(10) = rhs;
            if isa(vardata, 'categorical') || isa(vardata, 'string')
                % Already enforced that rhsValue is a string for a categorical var
            elseif ~isscalar(rhsValue)
                if isempty(rhsValue)
                    error(message('MATLAB:datatypes:InvalidValue', colname));
                else
                    error(message('MATLAB:subsassignnumelmismatch'));
                end
            end
            subsrefStruct = struct('type',{'.','()'},'subs',{colname,{row}});
            % Generate code only if the new value is different
            if row>size(a,1) || ~isequal(subsref(a,subsrefStruct),rhsValue)
                % If the table has only one row and this edit expands the
                % number of rows, then specify the column as 1 to prevent
                % the table variable growing horizontally.
                if size(a,1)==1 && row>1 % force the var to grow vertically
                    str = [varname '.' colname '(' num2str(row) ',1) = ' rhs ';'];
                else 
                    str = [varname '.' colname '(' num2str(row) ') = ' rhs ';'];
                end
            end
        end
    end
elseif varIndices(end)==col % Editing one column beyond the table grid
    varName = matlab.internal.table.dfltVarNames(size(a,2)+1,true);
    varName = matlab.lang.makeUniqueStrings(varName,a.varDim.labels,namelengthmax);
    
    % If rhs is a string or a numeric non-scalar, add the variable as a cell
    % array. Otherwise, add it as its native type.
    rhsValue = evalin('caller',rhs);
    if ~isempty(regexp(rhs,'^''.*''$','once')) || ischar(rhsValue) || ...
           iscell(rhsValue) || (isnumeric(rhsValue) && ~isscalar(rhsValue)) 
        str = [varname '.' varName  '{' num2str(row) ',1} = ' rhs ';'];
    else
        str = [varname '.' varName  '(' num2str(row) ',1) = ' rhs ';'];
    end
end