matlab app 学习笔记:UITable表处理及撤销操作

第一篇matlab app 学习笔记:新建app项目

​第二篇matlab app 学习笔记:新建选项卡组TabGroup、面板Panel、按钮Button、表UITable  

第三篇matlab app 学习笔记:删除列表和删除项目  

第四篇matlab app 学习笔记:添加数据管理  ​

一、添加UITable表删除操作

在app.Tab_datamanage页面,在app.panel_datamanage面板内新增一个面板app.panel_datamanage2,在面板内增加三个按钮“删除行”(app.btn_deleterow_data)、“删除列”(app.btn_deletecol_data)、“清空”(app.btn_deleteall_data)。

(一)增加“删除行”(app.btn_deleterow_data)的回调函数

回调函数的思路是先获取用户选择selects=app.UITable_data.Selection,再筛选出选择的行uniquerows=unique(rows),最后将这些行的值设置为空app.UITable_data.Data(uniquerows,:)=[];同时将行名的对应部分也清空(如有)app.UITable_data.RowName(uniquerows)=[];。

function btn_deleterow_dataButtonPushed(app, event)
            
            try
                selects=app.UITable_data.Selection;%获取用户选择的单元格列表(二维数组,选择模式是cell)
                if ~isempty(selects)
                    rows=selects(:,1);%获得行数组
                    uniquerows=unique(rows);%去除重复项
                    app.UITable_data.Data(uniquerows,:)=[];%将选择的行的数据清空,即删除行
                    if ~isempty(app.UITable_data.RowName)
                        app.UITable_data.RowName(uniquerows)=[];%删除对应的行名(如有)
                    end
                end
                
            catch ME
                errordlg(ME.message);%如果发生错误,弹出错误提示框
            end
        end

(二)增加“删除列”(app.btn_deletecol_data)的回调函数

回调函数的思路与上面的删除行一致。代码如下:

function btn_deletecol_dataButtonPushed(app, event)

            try
                selects=app.UITable_data.Selection;
                if isempty(selects)
                    return;
                end
                selectedColumns = selects(:,2);%获取列数组
                uniqueColumns = unique(selectedColumns)';%去重并排序
                app.UITable_data.Data(:,uniqueColumns)=[];%删除列
                if ~isempty(app.UITable_data.ColumnName)
                    app.UITable_data.ColumnName(uniqueColumns)=[];%删除列名
                end


            catch ME
                errordlg(ME.message);
            end
        end

 (三)增加“清空”(app.btn_deleteall_data)的回调函数

代码如下:

function btn_deleteall_dataButtonPushed(app, event)
           
            app.UITable_data.Data=[];
           
        end

二、添加UITable列查找操作

当UITable中的列很多时,要查找某个参数的数据会比较困难,因此增加按列名查找的功能。

在app.panel_datamanage面板内新增一个面板app.panel_datamanage3,在面板内增加编辑字段(文本)(查找输入框)app.editfield_findcol_data,和按钮“查找”app.btn_findcol_data。

回调函数有两个:

  • 编辑字段(文本)(查找输入框)app.editfield_findcol_data的ValueChanged回调,当用户输入完成点击回车时生效;
  • “查找”app.btn_findcol_data的回调函数,用户点击时生效,该回调直接调用编辑字段的回调即可。

代码如下:

function editfield_findcol_dataValueChanged(app, event)
            %通过lower将用户输入的字符和列名转化为小写,在列名中查找用户输入的列名,并将表的选择置于列的第一个cell
            find_value = lower(app.editfield_findcol_data.Value);%获取用户输入并转化为小写
            cols=lower(app.UITable_data.ColumnName);%获取表列名并转化为小写
            try
                col = find(contains(cols, find_value));%查找列名所在的位置,contains返回大小与cols相同的逻辑数组,find找的其中为true的值的位置
                scroll(app.UITable_data, 'column', col);%将UITable按列滚动到查找到的列处
                app.UITable_data.Selection=[1,col];%将UITable的选择设置为查到到的列的第一个cell
            catch ME
                errordlg(ME.message);
            end
        end

function btn_findcol_dataButtonPushed(app, event)
            app.editfield_findcol_dataValueChanged;%调用现有回调函数
        end

三、添加单元格内容显示控件

由于UITable控件默认显示小数位数为4位,本可以通过format设置显示格式,但大量数据显示全部小数位数并不利于数据处理,我们往往只是需要查看特定单元的实际数值,就可以通过添加一个编辑字段控件来显示用户选择的table表格中cell对应的数据。

在app.panel_datamanage面板内新增一个面板app.panel_datamanage4,在面板内增加编辑字段(数值)app.editfield_findcol_data,和按钮“查找”app.editfield_selectedcell_data。

这里添加的回调函数是UITable的回调,即当用户选择发生变化后的回调。代码如下:

function UITable_dataSelectionChanged(app, event)
            selection = app.UITable_data.Selection;%获取用户选择的单元格
            last_cell=selection(end,:);%选择最后一个单元格
            app.editfield_selectedcell_data.Value= table2array(app.UITable_data.Data(last_cell(1),last_cell(2)));%将单元格的信息显示在editfield上
        end

四、添加撤销操作

当我们编辑表格等内容时,往往存在错误操作需要返回上一步的情况,这时候撤销操作显得尤为重要,二小操作的步骤如下:

1.将用户的操作即数据记录下来

涉及UITable的操作,在本页面有:删除行、删除列、清空、编辑单元格。我们为每一个操作增加一个记录更改前数据和更改后数据的记录,并记录在程序的属性logOperation。

在app中增加三个参数:

        MaxUndoLevels = 5;  % 最大撤销步数
        LogBuffer = {};     % 操作日志记录
        CurrentIndex = 0 ;  % 当前操作位置

删除行在原按钮的回调函数中增加代码后如下:

function btn_deleterow_dataButtonPushed(app, event)
            
            %前三行为增加代码,记录更改前的表数据
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            
            try
                selects=app.UITable_data.Selection;%获取用户选择的单元格列表(二维数组,选择模式是cell)
                if ~isempty(selects)
                    rows=selects(:,1);%获得行数组
                    uniquerows=unique(rows);%去除重复项
                    app.UITable_data.Data(uniquerows,:)=[];%将选择的行的数据清空,即删除行
                    if ~isempty(app.UITable_data.RowName)
                        app.UITable_data.RowName(uniquerows)=[];%删除对应的行名(如有)
                    end
                end
                %后面三行增加的代码记录修改后的数据
                newData=app.UITable_data.Data;
                newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
                newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
                %接下来通过logOperation函数记录变更类型、变更对象、原数据,新数据到LogBuffer
                app.logOperation('tableEdit','UITable_data',preData,newData);
                %由于用于有了新的操作,将记录操作步骤置为当前
                app.CurrentIndex=height(app.LogBuffer);
            catch ME
                errordlg(ME.message);%如果发生错误,弹出错误提示框
            end
        end

删除列在原按钮的回调函数中增加代码后如下:

% Button pushed function: btn_deletecol_data
        function btn_deletecol_dataButtonPushed(app, event)
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            try
                selects=app.UITable_data.Selection;
                if isempty(selects)
                    return;
                end
                selectedColumns = selects(:,2);%获取列数组
                uniqueColumns = unique(selectedColumns)';%去重并排序
                app.UITable_data.Data(:,uniqueColumns)=[];%删除列
                if ~isempty(app.UITable_data.ColumnName)
                    app.UITable_data.ColumnName(uniqueColumns)=[];%删除列名
                end

                newData=app.UITable_data.Data;
                newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
                newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
                app.logOperation('tableEdit','UITable_data',preData,newData);
                app.CurrentIndex=height(app.LogBuffer);
            catch ME
                errordlg(ME.message);
            end
        end

清空在原按钮的回调函数中增加代码后如下:

function btn_deleteall_dataButtonPushed(app, event)
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            app.UITable_data.Data=[];
            newData=app.UITable_data.Data;
            newData.Properties.VariableNames=[];%存储列名
            newData.Properties.RowNames=[];
            app.logOperation('tableEdit','UITable_data',preData,newData);
            app.CurrentIndex=height(app.LogBuffer);

        end

编辑单元格的回调时UITable的回调函数,代码如下:

% Cell edit callback: UITable_data
        function UITable_dataCellEdit(app, event)
            indices = event.Indices;%编辑单元格的行列数组,如[1,2]为第1行第2列
            preData=event.PreviousData;%修改前的单元格数据
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            pretabledata=app.UITable_data.Data;%当前表数据赋值给修改前的数据存储
            pretabledata(indices(1),indices(2))=table(preData);%将修改前的数据存储中已经修改过的数据改回原来的值
            newData = app.UITable_data.Data;%保存新的数据
            newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            app.logOperation('tableEdit','UITable_data',pretabledata,newData);%存储修改类型、控件名称、原数据、新数据到LogBuffer
            app.CurrentIndex=height(app.LogBuffer);
        end

logOperation函数如下:

function logOperation(app, actionType, targetId,preData,newData)
            app.LogBuffer = [app.LogBuffer; {datetime('now'), actionType, targetId, preData,newData}];%在LogBuffer 下一行增加新的操作数据
            app.CurrentIndex = height(app.LogBuffer);%因为人为修改了数据,将操作顺序的记录置为当前
            if height(app.LogBuffer) > app.MaxUndoLevels%如果LogBuffer 数量超过了预定的长度(允许撤销的次数),将第一个操作置空删除
                app.LogBuffer(1,:) = [];
            end
        end

2.建立工具栏和撤销、重做按钮

在UIFigure下新家一个工具栏toolbar,并添加按钮工具app.PushTool_undo和app.PushTool_redo。

PushTool_undo用于撤销操作,PushTool_redo用于重做操作。

对PushTool_undo添加回调函数:

 % Callback function: PushTool_undo
        function PushTool_undoClicked(app, event)
            if app.CurrentIndex > 0 
                app.undoAction(app.CurrentIndex);%调用undo函数
                if app.CurrentIndex>1
                    app.CurrentIndex = app.CurrentIndex - 1;%将序号调整到前一步操作
                end
            end

        end

        function undoAction(app,index)
            if index>=1&&index<=height(app.LogBuffer)
                op = app.LogBuffer(index, :);%获取当前操作序号的记录
                switch op{2}
                    case 'tableEdit'%判断修改类型,如果为tableEdit,表编辑,我自定义的
                        app.(op{3}).Data = op{4};%将存在的原数据加载到表app.(op{3})是通过控件名称调用控件的方式即app.('UITable_data')
                        app.(op{3}).ColumnName=op{4}.Properties.VariableNames;%将原列名赋值给UITable
                        app.(op{3}).RowName=op{4}.Properties.RowNames;%将原行名赋值给UITable
                    case 'textInput'
                        app.(op{3}).Value = op{4};
                        % 可扩展其他控件类型
                end
            end
        end

对PushTool_redo添加回调函数:

% Callback function: PushTool_redo
        function PushTool_redoClicked(app, event)
            if app.CurrentIndex > 0
                app.redoAction(app.CurrentIndex);
                if app.CurrentIndex<height(app.LogBuffer)
                    app.CurrentIndex = app.CurrentIndex + 1;
                end
            end
        end

        function redoAction(app,index)
            if index>=1&&index<=height(app.LogBuffer)
                op = app.LogBuffer(index, :);
                switch op{2}
                    case 'tableEdit'
                        app.(op{3}).Data = op{5};%将新数据重新赋值给UITable
                        app.(op{3}).ColumnName=op{5}.Properties.VariableNames;
                        app.(op{3}).RowName=op{5}.Properties.RowNames;
                    case 'textInput'
                        app.(op{3}).Value = op{5};
                        % 可扩展其他控件类型
                end
            end
        end

五、完整代码

classdef app_01 < matlab.apps.AppBase

    % Properties that correspond to app components
    properties (Access = public)
        UIFigure                       matlab.ui.Figure
        Toolbar                        matlab.ui.container.Toolbar
        PushTool_undo                  matlab.ui.container.toolbar.PushTool
        PushTool_redo                  matlab.ui.container.toolbar.PushTool
        TabGroup                       matlab.ui.container.TabGroup
        Tab_projects                   matlab.ui.container.Tab
        EditField_loadedproject        matlab.ui.control.EditField
        EditFieldLabel                 matlab.ui.control.Label
        Panel_projects                 matlab.ui.container.Panel
        Button_saveproject             matlab.ui.control.Button
        Button_loadproject             matlab.ui.control.Button
        Button_deleteproject_fromlist  matlab.ui.control.Button
        Button_deleteproject           matlab.ui.control.Button
        Button_newprohject             matlab.ui.control.Button
        UITable_projectlist            matlab.ui.control.Table
        Tab_datamanage                 matlab.ui.container.Tab
        UITable_data                   matlab.ui.control.Table
        panel_datamanage               matlab.ui.container.Panel
        panel_datamanage1              matlab.ui.container.Panel
        Button_savedata                matlab.ui.control.Button
        Button_loaddata                matlab.ui.control.Button
        Button_importdatafromexcel     matlab.ui.control.Button
        Button_outputdatatoexcel       matlab.ui.control.Button
        panel_datamanage2              matlab.ui.container.Panel
        btn_deleterow_data             matlab.ui.control.Button
        btn_deletecol_data             matlab.ui.control.Button
        btn_deleteall_data             matlab.ui.control.Button
        panel_datamanage3              matlab.ui.container.Panel
        editfield_findcol_data         matlab.ui.control.EditField
        Label                          matlab.ui.control.Label
        btn_findcol_data               matlab.ui.control.Button
        panel_datamanage4              matlab.ui.container.Panel
        editfield_selectedcell_data    matlab.ui.control.NumericEditField
        Label_2                        matlab.ui.control.Label
    end


    properties (Access = private)
        projects_info=[]; % 存储项目信息

        project_name;%项目名称
        project_dir;%项目地址
        create_time;%创建时间
        last_modefied_time;%最后修改时间
        data=[];%存储主数据

        MaxUndoLevels = 5;  % 最大撤销步数
        LogBuffer = {};     % 操作日志
        CurrentIndex = 0 ;  % 当前操作位置
    end

    methods (Access = private)

        function save_projects_info(app)%将projects info保存到本地
            projects_info=app.projects_info;
            save("projects_info.mat","projects_info");
        end

        function logOperation(app, actionType, targetId,preData,newData)
            app.LogBuffer = [app.LogBuffer; {datetime('now'), actionType, targetId, preData,newData}];
            app.CurrentIndex = height(app.LogBuffer);
            if height(app.LogBuffer) > app.MaxUndoLevels
                app.LogBuffer(1,:) = [];
            end
        end

        function undoAction(app,index)
            if index>=1&&index<=height(app.LogBuffer)
                op = app.LogBuffer(index, :);
                switch op{2}
                    case 'tableEdit'
                        app.(op{3}).Data = op{4};
                        app.(op{3}).ColumnName=op{4}.Properties.VariableNames;%存储列名
                        app.(op{3}).RowName=op{4}.Properties.RowNames;%存储行名
                    case 'textInput'
                        app.(op{3}).Value = op{4};
                        % 可扩展其他控件类型
                end
            end
        end

        function redoAction(app,index)
            if index>=1&&index<=height(app.LogBuffer)
                op = app.LogBuffer(index, :);
                switch op{2}
                    case 'tableEdit'
                        app.(op{3}).Data = op{5};
                        app.(op{3}).ColumnName=op{5}.Properties.VariableNames;%存储列名
                        app.(op{3}).RowName=op{5}.Properties.RowNames;%存储行名
                    case 'textInput'
                        app.(op{3}).Value = op{5};
                        % 可扩展其他控件类型
                end
            end
        end
    end



    % Callbacks that handle component events
    methods (Access = private)

        % Code that executes after component creation
        function startupFcn(app)
            %导入项目清单
            try
                folder=pwd;
                fulefilename=fullfile(folder, 'projects_info.mat');
                if exist(fulefilename,"file")
                    projectsinfo=load("projects_info.mat");
                    app.projects_info=projectsinfo.projects_info;
                    app.UITable_projectlist.Data=app.projects_info;
                end
            catch ME
                errordlg(sprintf('错误  %s',ME.message));
            end
        end

        % Cell edit callback: UITable_data
        function UITable_dataCellEdit(app, event)
            indices = event.Indices;
            preData=event.PreviousData;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            pretabledata=app.UITable_data.Data;
            pretabledata(indices(1),indices(2))=table(preData);
            newData = app.UITable_data.Data;
            newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            app.logOperation('tableEdit','UITable_data',pretabledata,newData);
            app.CurrentIndex=height(app.LogBuffer);
        end

        % Callback function: PushTool_undo
        function PushTool_undoClicked(app, event)
            if app.CurrentIndex > 0
                app.undoAction(app.CurrentIndex);
                if app.CurrentIndex>1
                    app.CurrentIndex = app.CurrentIndex - 1;
                end
            end

        end

        % Callback function: PushTool_redo
        function PushTool_redoClicked(app, event)
            if app.CurrentIndex > 0
                app.redoAction(app.CurrentIndex);
                if app.CurrentIndex<height(app.LogBuffer)
                    app.CurrentIndex = app.CurrentIndex + 1;
                end
            end
        end

        % Button pushed function: Button_newprohject
        function Button_newprohjectPushed(app, event)
            %第一部分:提示是否新建项目
            selection = uiconfirm(app.UIFigure,"新建项目前请确认保存的现有的项目,是否开始新建项目?","确认新建项目", ...
                "Icon","warning");
            if isequal('Cancel',selection)
                return
            end

            %第二部分:通过编程代码的方式建立新的新建对话框
            d = dialog('Position',[500 400 500 250],'Name','新建项目');
            %项目名称
            name_label = uicontrol('Parent',d,...
                'Style','text',...
                'Position',[30 210 100 20],...
                'String','项目名称');
            name_txt=uicontrol('Parent',d,...
                'Style','edit',...
                'Position',[120 210 300 20],...
                HorizontalAlignment='left');
            %项目说明
            info_label = uicontrol('Parent',d,...
                'Style','text',...
                'Position',[30 150 100 20],...
                'String','项目说明');
            info_txt=uicontrol('Parent',d,...
                'Style','edit',...
                'Position',[120 130 300 60],...
                'Min',0,'Max',1000,...
                'String','',...
                HorizontalAlignment='left');
            %保存地址
            foldernow=pwd;%获取当前文件地址
            folder_label = uicontrol('Parent',d,...
                'Style','text',...
                'Position',[30 100 100 20],...
                'String','项目地址');
            folder_txt=uicontrol('Parent',d,...
                'Style','edit',...
                'Position',[120 100 300 20],...
                'String',foldernow,...
                HorizontalAlignment='left');
            button_folder = uicontrol('Parent',d,...
                'Style','pushbutton',...
                'Position',[420 97 50 25],...
                'String','选择',...
                Callback=@button_folder_Pushed);
            %确定按钮
            button_done = uicontrol('Parent',d,...
                'Style','pushbutton',...
                'Position',[350 20 70 25],...
                'String','确定',...
                Callback=@button_done_Pushed);

            %第三部分:新建对话框中回调函数
            function button_folder_Pushed(src,event)%按钮选择btn_folder(选择)的回调函数
                foldernow=pwd;%获取当前文件地址
                try
                    newdir=uigetdir(foldernow,'选择文件夹');
                    folder_txt.String=newdir;
                catch ME
                    errordlg(sprintf('失败  %s',ME.message));
                end
            end


            function button_done_Pushed(src,event)%按钮选择button_done(确定)的回调函数
                name=name_txt.get('String');
                info=info_txt.get('String');
                projectdir=folder_txt.get('string');
                if ~isempty(name)
                    timenow=datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss', 'TimeZone', 'local');
                    col1=name;
                    col2=char(timenow);
                    col3=char(timenow);
                    col4=projectdir;
                    col5=info;
                    row_data={col1,col2,col3,col4,col5};
                    %新建文件夹
                    try
                        newdir=char(sprintf('%s/%s',projectdir,name));
                        if ~exist(projectdir,'dir')
                            mkdir(projectdir);
                        end
                        mkdir(newdir);

                        %赋初值
                        app.project_name=name;%项目名称
                        app.project_dir=projectdir;%项目地址
                        app.create_time=col2;%创建时间
                        app.last_modefied_time=col3;%最后修改时间
                        app.data=[];

                        app.projects_info=[app.projects_info;row_data];
                        app.UITable_projectlist.Data=app.projects_info;
                        app.EditField_loadedproject.Value=name;
                        app.save_projects_info;
                        app.Button_saveprojectPushed;
                        delete(d);
                    catch ME
                        rmdir(newdir, 's');
                        errordlg(ME.message);
                        errordlg(sprintf('失败  %s',ME.message));
                        delete(d);
                    end
                end

            end
        end

        % Button pushed function: Button_deleteproject_fromlist
        function Button_deleteproject_fromlistPushed(app, event)
            selects=app.UITable_projectlist.Selection;
            rows=selects(1,:);
            try
                app.projects_info(rows,:)=[];
                app.UITable_projectlist.Data=app.projects_info;
                app.save_projects_info;
            catch ME
                errordlg(ME.message);
            end

        end

        % Button pushed function: Button_deleteproject
        function Button_deleteprojectPushed(app, event)
            selection = uiconfirm(app.UIFigure,"选择“确定”后该项目的所有本地文件都将删除,是否仍要删除?","确认删除", ...
                "Icon","warning");
            if isequal('Cancel',selection)
                return;
            end


            selects=app.UITable_projectlist.Selection;
            rows=selects(:,1);
            rows=unique(rows);
            for i=height(rows):-1:1
                try
                    row=rows(i,1);
                    name=cell2mat(app.projects_info(row,1));
                    projectdir=cell2mat(app.projects_info(row,4));
                    deldir=fullfile(projectdir,name);
                    rmdir(deldir, 's');
                    app.projects_info(row,:)=[];
                catch ME
                    errordlg(ME.message);
                end
            end
            app.UITable_projectlist.Data=app.projects_info;
            app.save_projects_info;
        end

        % Button pushed function: Button_savedata
        function Button_savedataButtonPushed(app, event)
            try
                if ~isempty(app.UITable_data.Data)
                    app.data=app.UITable_data.Data;%存储数据
                    app.data.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
                    app.data.Properties.RowNames=app.UITable_data.RowName;%存储行名
                end
            catch ME
                errordlg(ME.message);
            end
        end

        % Button pushed function: Button_loaddata
        function Button_loaddataButtonPushed(app, event)
            try
                app.UITable_data.Data=app.data;%显示数据
                app.UITable_data.ColumnName=app.data.Properties.VariableNames;%显示列名
                app.UITable_data.RowName=app.data.Properties.RowNames;%显示行名
            catch ME
                errordlg(ME.message);
            end
        end

        % Button pushed function: Button_importdatafromexcel
        function Button_importdatafromexcelButtonPushed(app, event)
            try
                [file, location] = uigetfile({'*.xlsx','*.csv'}, '选择要导入的Excel文件');
                fullfilename = fullfile(location, file);
                sheets=sheetnames(fullfilename);
                %导入选项
                d = dialog('Position',[500 500 500 120],'Name','导入设置');
                sheet_label = uicontrol('Parent',d,...
                    'Style','text',...
                    'Position',[30 60 100 40],...
                    'String','选择Sheet');
                sheet_list=uicontrol('Parent',d,...
                    'Style','popupmenu',...
                    'String',sheets,...
                    'Position',[120 65 200 40]);
                check_row=uicontrol('Parent',d,...
                    'Style','checkbox',...
                    'String','读取首列为行名称',...
                    'Value',1,...
                    'Position',[340 75 150 40]);
                %确定按钮
                btn_done = uicontrol('Parent',d,...
                    'Position',[340 40 70 25],...
                    'String','确定',...
                    Callback=@btn_done_Pushed);
            catch ME
                errordlg(ME.message);
            end

            function btn_done_Pushed(src,event)
                try
                    %读取数据
                    sheet_value=sheet_list.get('Value');
                    sheet_str=sheets(sheet_value);
                    read_row_name=check_row.get('Value');
                    readdata = readtable(fullfilename,"Sheet",sheet_str,ReadRowNames=read_row_name,VariableNamingRule="preserve");
                    app.UITable_data.Data=readdata;
                    app.UITable_data.RowName=readdata.Properties.RowNames;
                    app.UITable_data.ColumnName=readdata.Properties.VariableNames;
                    app.data=readdata;
                    delete(gcf);
                catch ME
                    errordlg(ME.message);
                    delete(gcf);
                end
            end
        end

        % Button pushed function: Button_outputdatatoexcel
        function Button_outputdatatoexcelButtonPushed(app, event)
            try
                app.data=app.UITable_data.Data;%试验数据
                app.data.Properties.VariableNames=app.UITable_data.ColumnName;
                app.data.Properties.RowNames=app.UITable_data.RowName;
                try
                    [file,location,~] = uiputfile('*.xlsx','选择文件夹','data_out');
                    filename=fullfile(location,file);
                    writetable(app.data,filename,"WriteVariableNames",true);
                catch ME
                    errordlg(ME.message);
                end
            catch ME
                errordlg(ME.message);
            end
        end

        % Selection change function: TabGroup
        function TabGroupSelectionChanged(app, event)
            %判断是否加载了项目,如果没有,则返回到项目管理页面
            selectedTab = app.TabGroup.SelectedTab;
            if isempty(app.EditField_loadedproject.Value)
                if ~isequal(selectedTab,app.Tab_projects)
                    app.TabGroup.SelectedTab=app.Tab_projects;
                    warndlg('请先加载项目或新建项目。');
                end
            end
        end

        % Button pushed function: Button_loadproject
        function Button_loadprojectPushed(app, event)
            selects=app.UITable_projectlist.Selection;
            [m,~]=size(selects);
            if m==1
                try
                    row=selects(1);
                    name=cell2mat(app.UITable_projectlist.Data(row,1));
                    projectdir=cell2mat(app.UITable_projectlist.Data(row,4));
                    filename=fullfile(projectdir,name,'data.mat');
                    data=load(filename);

                    app.project_name=data.project_name;%项目名称
                    app.project_dir=data.project_dir;%项目地址
                    app.create_time=data.create_time;%创建时间
                    app.last_modefied_time=data.last_modefied_time;%最后修改时间
                    app.data=data.data;%试验数据

                    %显示数据
                    app.EditField_loadedproject.Value=app.project_name;%为加载项目
                    app.UITable_data.Data=app.data;%显示试验数据
                    app.UITable_data.ColumnName=app.data.Properties.VariableNames;%显示列名
                    app.UITable_data.RowName=app.data.Properties.RowNames;%显示行名
                catch ME
                    errordlg(ME.message);
                end
            end
        end

        % Button pushed function: Button_saveproject
        function Button_saveprojectPushed(app, event)
            app.Button_savedataButtonPushed;
            project_name=app.project_name;%项目名称
            project_dir=app.project_dir;%项目保存地址
            create_time=app.create_time;%创建时间
            last_modefied_time=app.last_modefied_time;%最后修改时间
            data=app.data;%试验数据
            app.last_modefied_time=char(datetime('now', 'Format', 'yyyy-MM-dd HH:mm:ss', 'TimeZone', 'local'));

            try
                filename=fullfile(project_dir,project_name,'data.mat');
                save(filename,"project_name","project_dir","create_time","last_modefied_time","data");
                project_names=app.projects_info(:,1);
                row=find(contains(project_names,project_name));
                app.projects_info(row,3)={app.last_modefied_time};
                app.UITable_projectlist.Data=app.projects_info;
            catch ME
                errordlg(ME.message);
            end
        end

        % Button pushed function: btn_deleterow_data
        function btn_deleterow_dataButtonPushed(app, event)
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            try
                selects=app.UITable_data.Selection;%获取用户选择的单元格列表(二维数组,选择模式是cell)
                if ~isempty(selects)
                    rows=selects(:,1);%获得行数组
                    uniquerows=unique(rows);%去除重复项
                    app.UITable_data.Data(uniquerows,:)=[];%将选择的行的数据清空,即删除行
                    if ~isempty(app.UITable_data.RowName)
                        app.UITable_data.RowName(uniquerows)=[];%删除对应的行名(如有)
                    end
                end
                newData=app.UITable_data.Data;
                newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
                newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
                app.logOperation('tableEdit','UITable_data',preData,newData);
                app.CurrentIndex=height(app.LogBuffer);
            catch ME
                errordlg(ME.message);%如果发生错误,弹出错误提示框
            end
        end

        % Button pushed function: btn_deletecol_data
        function btn_deletecol_dataButtonPushed(app, event)
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            try
                selects=app.UITable_data.Selection;
                if isempty(selects)
                    return;
                end
                selectedColumns = selects(:,2);%获取列数组
                uniqueColumns = unique(selectedColumns)';%去重并排序
                app.UITable_data.Data(:,uniqueColumns)=[];%删除列
                if ~isempty(app.UITable_data.ColumnName)
                    app.UITable_data.ColumnName(uniqueColumns)=[];%删除列名
                end

                newData=app.UITable_data.Data;
                newData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
                newData.Properties.RowNames=app.UITable_data.RowName;%存储行名
                app.logOperation('tableEdit','UITable_data',preData,newData);
                app.CurrentIndex=height(app.LogBuffer);
            catch ME
                errordlg(ME.message);
            end
        end

        % Button pushed function: btn_deleteall_data
        function btn_deleteall_dataButtonPushed(app, event)
            preData=app.UITable_data.Data;
            preData.Properties.VariableNames=app.UITable_data.ColumnName;%存储列名
            preData.Properties.RowNames=app.UITable_data.RowName;%存储行名
            app.UITable_data.Data=[];
            newData=app.UITable_data.Data;
            newData.Properties.VariableNames=[];%存储列名
            newData.Properties.RowNames=[];
            app.logOperation('tableEdit','UITable_data',preData,newData);
            app.CurrentIndex=height(app.LogBuffer);

        end

        % Value changed function: editfield_findcol_data
        function editfield_findcol_dataValueChanged(app, event)
            %通过lower将用户输入的字符和列名转化为小写,在列名中查找用户输入的列名,并将表的选择置于列的第一个cell
            find_value = lower(app.editfield_findcol_data.Value);%获取用户输入并转化为小写
            cols=lower(app.UITable_data.ColumnName);%获取表列名并转化为小写
            try
                col = find(contains(cols, find_value));%查找列名所在的位置,contains返回大小与cols相同的逻辑数组,find找的其中为true的值的位置
                scroll(app.UITable_data, 'column', col);%将UITable按列滚动到查找到的列处
                app.UITable_data.Selection=[1,col];%将UITable的选择设置为查到到的列的第一个cell
            catch ME
                errordlg(ME.message);
            end
        end

        % Button pushed function: btn_findcol_data
        function btn_findcol_dataButtonPushed(app, event)
            app.editfield_findcol_dataValueChanged;%调用现有回调函数
        end

        % Selection changed function: UITable_data
        function UITable_dataSelectionChanged(app, event)
            selection = app.UITable_data.Selection;%获取用户选择的单元格
            last_cell=selection(end,:);%选择最后一个单元格
            app.editfield_selectedcell_data.Value= table2array(app.UITable_data.Data(last_cell(1),last_cell(2)));%将单元格的信息显示在editfield上
        end
    end

    % Component initialization
    methods (Access = private)

        % Create UIFigure and components
        function createComponents(app)

            % Get the file path for locating images
            pathToMLAPP = fileparts(mfilename('fullpath'));

            % Create UIFigure and hide until all components are created
            app.UIFigure = uifigure('Visible', 'off');
            app.UIFigure.Position = [10 60 1520 860];
            app.UIFigure.Name = '第一个app';
            app.UIFigure.Icon = fullfile(pathToMLAPP, 'icon01.png');

            % Create Toolbar
            app.Toolbar = uitoolbar(app.UIFigure);

            % Create PushTool_undo
            app.PushTool_undo = uipushtool(app.Toolbar);
            app.PushTool_undo.ClickedCallback = createCallbackFcn(app, @PushTool_undoClicked, true);
            app.PushTool_undo.Icon = fullfile(pathToMLAPP, 'ondo.png');

            % Create PushTool_redo
            app.PushTool_redo = uipushtool(app.Toolbar);
            app.PushTool_redo.ClickedCallback = createCallbackFcn(app, @PushTool_redoClicked, true);
            app.PushTool_redo.Icon = fullfile(pathToMLAPP, 'redo.png');

            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.SelectionChangedFcn = createCallbackFcn(app, @TabGroupSelectionChanged, true);
            app.TabGroup.Position = [0 1 1520 859];

            % Create Tab_projects
            app.Tab_projects = uitab(app.TabGroup);
            app.Tab_projects.Title = '项目管理';

            % Create UITable_projectlist
            app.UITable_projectlist = uitable(app.Tab_projects);
            app.UITable_projectlist.ColumnName = {'项目名称'; '创建时间'; '最后修改时间'; '项目地址'; '项目说明'};
            app.UITable_projectlist.RowName = {};
            app.UITable_projectlist.Position = [17 20 1480 666];

            % Create Panel_projects
            app.Panel_projects = uipanel(app.Tab_projects);
            app.Panel_projects.Position = [1 730 1520 105];

            % Create Button_newprohject
            app.Button_newprohject = uibutton(app.Panel_projects, 'push');
            app.Button_newprohject.ButtonPushedFcn = createCallbackFcn(app, @Button_newprohjectPushed, true);
            app.Button_newprohject.Icon = fullfile(pathToMLAPP, 'new.svg');
            app.Button_newprohject.IconAlignment = 'top';
            app.Button_newprohject.Position = [16 22 60 60];
            app.Button_newprohject.Text = '新建项目';

            % Create Button_deleteproject
            app.Button_deleteproject = uibutton(app.Panel_projects, 'push');
            app.Button_deleteproject.ButtonPushedFcn = createCallbackFcn(app, @Button_deleteprojectPushed, true);
            app.Button_deleteproject.Icon = fullfile(pathToMLAPP, 'delete.svg');
            app.Button_deleteproject.IconAlignment = 'top';
            app.Button_deleteproject.FontColor = [1 0 0];
            app.Button_deleteproject.Tooltip = {'注意:删除项目会删除所有项目文件。'};
            app.Button_deleteproject.Position = [312 22 60 60];
            app.Button_deleteproject.Text = '删除项目';

            % Create Button_deleteproject_fromlist
            app.Button_deleteproject_fromlist = uibutton(app.Panel_projects, 'push');
            app.Button_deleteproject_fromlist.ButtonPushedFcn = createCallbackFcn(app, @Button_deleteproject_fromlistPushed, true);
            app.Button_deleteproject_fromlist.Icon = fullfile(pathToMLAPP, 'delete_modifiedList.svg');
            app.Button_deleteproject_fromlist.IconAlignment = 'top';
            app.Button_deleteproject_fromlist.Tooltip = {'仅从列表中移除,不会删除数据文件及文件夹。'};
            app.Button_deleteproject_fromlist.Position = [239 22 60 60];
            app.Button_deleteproject_fromlist.Text = '剔除列表';

            % Create Button_loadproject
            app.Button_loadproject = uibutton(app.Panel_projects, 'push');
            app.Button_loadproject.ButtonPushedFcn = createCallbackFcn(app, @Button_loadprojectPushed, true);
            app.Button_loadproject.Icon = fullfile(pathToMLAPP, 'open_selectedWorkspace.svg');
            app.Button_loadproject.IconAlignment = 'top';
            app.Button_loadproject.Position = [163 22 63 60];
            app.Button_loadproject.Text = '加载项目';

            % Create Button_saveproject
            app.Button_saveproject = uibutton(app.Panel_projects, 'push');
            app.Button_saveproject.ButtonPushedFcn = createCallbackFcn(app, @Button_saveprojectPushed, true);
            app.Button_saveproject.Icon = fullfile(pathToMLAPP, 'saved.svg');
            app.Button_saveproject.IconAlignment = 'top';
            app.Button_saveproject.Position = [89 22 63 60];
            app.Button_saveproject.Text = '保存项目';

            % Create EditFieldLabel
            app.EditFieldLabel = uilabel(app.Tab_projects);
            app.EditFieldLabel.HorizontalAlignment = 'right';
            app.EditFieldLabel.Position = [17 697 89 22];
            app.EditFieldLabel.Text = '已经加载的项目';

            % Create EditField_loadedproject
            app.EditField_loadedproject = uieditfield(app.Tab_projects, 'text');
            app.EditField_loadedproject.Position = [121 697 487 22];

            % Create Tab_datamanage
            app.Tab_datamanage = uitab(app.TabGroup);
            app.Tab_datamanage.Title = '数据管理';

            % Create panel_datamanage
            app.panel_datamanage = uipanel(app.Tab_datamanage);
            app.panel_datamanage.Position = [1 730 1520 105];

            % Create panel_datamanage4
            app.panel_datamanage4 = uipanel(app.panel_datamanage);
            app.panel_datamanage4.Position = [519 8 168 93];

            % Create Label_2
            app.Label_2 = uilabel(app.panel_datamanage4);
            app.Label_2.HorizontalAlignment = 'right';
            app.Label_2.Position = [56 64 53 22];
            app.Label_2.Text = '单元格值';

            % Create editfield_selectedcell_data
            app.editfield_selectedcell_data = uieditfield(app.panel_datamanage4, 'numeric');
            app.editfield_selectedcell_data.ValueDisplayFormat = '%.15f';
            app.editfield_selectedcell_data.Position = [10 37 146 22];

            % Create panel_datamanage3
            app.panel_datamanage3 = uipanel(app.panel_datamanage);
            app.panel_datamanage3.Position = [393 8 119 93];

            % Create btn_findcol_data
            app.btn_findcol_data = uibutton(app.panel_datamanage3, 'push');
            app.btn_findcol_data.ButtonPushedFcn = createCallbackFcn(app, @btn_findcol_dataButtonPushed, true);
            app.btn_findcol_data.Position = [19 8 79 23];
            app.btn_findcol_data.Text = '查找';

            % Create Label
            app.Label = uilabel(app.panel_datamanage3);
            app.Label.HorizontalAlignment = 'right';
            app.Label.Position = [44 64 41 22];
            app.Label.Text = '查找列';

            % Create editfield_findcol_data
            app.editfield_findcol_data = uieditfield(app.panel_datamanage3, 'text');
            app.editfield_findcol_data.ValueChangedFcn = createCallbackFcn(app, @editfield_findcol_dataValueChanged, true);
            app.editfield_findcol_data.Position = [10 36 100 22];

            % Create panel_datamanage2
            app.panel_datamanage2 = uipanel(app.panel_datamanage);
            app.panel_datamanage2.Position = [260 8 126 93];

            % Create btn_deleteall_data
            app.btn_deleteall_data = uibutton(app.panel_datamanage2, 'push');
            app.btn_deleteall_data.ButtonPushedFcn = createCallbackFcn(app, @btn_deleteall_dataButtonPushed, true);
            app.btn_deleteall_data.FontColor = [1 0 0];
            app.btn_deleteall_data.Position = [13 9 100 23];
            app.btn_deleteall_data.Text = '清空';

            % Create btn_deletecol_data
            app.btn_deletecol_data = uibutton(app.panel_datamanage2, 'push');
            app.btn_deletecol_data.ButtonPushedFcn = createCallbackFcn(app, @btn_deletecol_dataButtonPushed, true);
            app.btn_deletecol_data.FontColor = [0.8667 0.3294 0];
            app.btn_deletecol_data.Position = [13 35 100 22];
            app.btn_deletecol_data.Text = '删除列';

            % Create btn_deleterow_data
            app.btn_deleterow_data = uibutton(app.panel_datamanage2, 'push');
            app.btn_deleterow_data.ButtonPushedFcn = createCallbackFcn(app, @btn_deleterow_dataButtonPushed, true);
            app.btn_deleterow_data.FontColor = [0.9608 0.4667 0.1608];
            app.btn_deleterow_data.Position = [13 62 100 23];
            app.btn_deleterow_data.Text = '删除行';

            % Create panel_datamanage1
            app.panel_datamanage1 = uipanel(app.panel_datamanage);
            app.panel_datamanage1.Position = [7 8 245 93];

            % Create Button_outputdatatoexcel
            app.Button_outputdatatoexcel = uibutton(app.panel_datamanage1, 'push');
            app.Button_outputdatatoexcel.ButtonPushedFcn = createCallbackFcn(app, @Button_outputdatatoexcelButtonPushed, true);
            app.Button_outputdatatoexcel.Position = [132 24 100 23];
            app.Button_outputdatatoexcel.Text = '导出到EXCEL';

            % Create Button_importdatafromexcel
            app.Button_importdatafromexcel = uibutton(app.panel_datamanage1, 'push');
            app.Button_importdatafromexcel.ButtonPushedFcn = createCallbackFcn(app, @Button_importdatafromexcelButtonPushed, true);
            app.Button_importdatafromexcel.Position = [132 63 100 23];
            app.Button_importdatafromexcel.Text = '从EXCEL导入';

            % Create Button_loaddata
            app.Button_loaddata = uibutton(app.panel_datamanage1, 'push');
            app.Button_loaddata.ButtonPushedFcn = createCallbackFcn(app, @Button_loaddataButtonPushed, true);
            app.Button_loaddata.Position = [12 25 100 22];
            app.Button_loaddata.Text = '加载数据';

            % Create Button_savedata
            app.Button_savedata = uibutton(app.panel_datamanage1, 'push');
            app.Button_savedata.ButtonPushedFcn = createCallbackFcn(app, @Button_savedataButtonPushed, true);
            app.Button_savedata.Position = [13 63 100 22];
            app.Button_savedata.Text = '保存数据';

            % Create UITable_data
            app.UITable_data = uitable(app.Tab_datamanage);
            app.UITable_data.ColumnName = {'Column 1'; 'Column 2'; 'Column 3'; 'Column 4'};
            app.UITable_data.RowName = {};
            app.UITable_data.ColumnEditable = true;
            app.UITable_data.CellEditCallback = createCallbackFcn(app, @UITable_dataCellEdit, true);
            app.UITable_data.SelectionChangedFcn = createCallbackFcn(app, @UITable_dataSelectionChanged, true);
            app.UITable_data.Position = [28 20 1469 694];

            % Show the figure after all components are created
            app.UIFigure.Visible = 'on';
        end
    end

    % App creation and deletion
    methods (Access = public)

        % Construct app
        function app = app_01

            % Create UIFigure and components
            createComponents(app)

            % Register the app with App Designer
            registerApp(app, app.UIFigure)

            % Execute the startup function
            runStartupFcn(app, @startupFcn)

            if nargout == 0
                clear app
            end
        end

        % Code that executes before app deletion
        function delete(app)

            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值