简介面向MATLAB初学者与需要快速处理Excel数据的科研、工程人员解决如何将工作表中的数据高效导入MATLAB工作区并供后续分析调用的问题。压缩包内共四个文件包含可直接运行的主程序、示例数据表格、文本格式的使用说明以及文档资料整体仅118KB轻量精炼。主程序采用交互式运行模式按提示操作即可查看读取结果适合零基础入门与日常实验参考。已有1980人学习下载具备一定参考价值。资源将主程序与示例数据分离便于对照理解代码逻辑通过跟随说明实践读者能够掌握MATLAB读取Excel的常用函数与标准流程并可将示例数据替换为自己的文件灵活应用于数据处理和建模分析任务中。1. 读Excel总是类型错乱先分清“表结构三分类”再选MATLAB函数我最早用MATLAB读Excel时下意识就是一句xlsread直到连续三次读同一份表格却分别拿到NaN、43000多和一堆乱码才意识到问题根本不在函数而在对数据形态的判断。同一份Excel里纯数值、数值文本混合、日期缺席处理方式完全不同。更麻烦的是读进来的数据长什么样取决于你调用的是xlsread、readtable还是readmatrix它们背后对应的读取引擎和类型规则根本不一样。这篇文章想解决的就是这件事拿到一份Excel后怎么快速判断该用哪个读取函数如何设置Sheet、Range、变量类型这些关键参数以及遇到NaN、日期序列号、大文件卡死时怎么排查。核心目标是把MATLAB读取Excel从“碰运气”变成“按形状选函数”让新老手都能少走弯路。2. 三类读取函数怎么选xlsread、readtable、readmatrix的适用边界与参数2.1 xlsread旧接口还在但新代码不该再用很多老代码里xlsread是绝对主力它的标准调用方式是一次返回三个输出[data, text, raw] xlsread(sales.xlsx, Sheet1, A1:D200);data是所有数值组成的矩阵text是文本内容构成的元胞数组raw是原始单元格数据的完整元胞数组。当某一列全是文本时data矩阵中这一列会被剔除而不是补NaN当整表只有一列文本时data很可能是空数组。这个行为常让人困惑明明表格有数值data却空着。从使用角度看xlsread的问题在于它依赖Excel组件接口在Linux服务器或未安装Excel的机器上经常直接报错而且每次调用可能启动一个隐形的Excel进程脚本结束后进程不一定会退出。新版MATLAB文档也不推荐在新代码里使用它。我一般只在调试别人遗留的老脚本时才会保留xlsread如果只是做数据读取会毫不犹豫地换到下面两个函数。另外要注意xlsread的第三返回参数raw可以用来检查单元格真实内容这对排查“为什么读出来不对”很有帮助但不要依赖它做大范围数据读取因为速度非常慢。2.2 readtable混合型表格的首选自动类型推断的双刃剑readtable是当前读取Excel最推荐的入口它返回table类型每一列有变量名直接对接后续的数据清洗、绘图和统计分析。最小调用是T readtable(sales.xlsx);这段代码会自动读取第一个工作表的全部数据并自动推断每列类型。如果某一列是纯数字就会解析成double如果一整列都是文本就会解析成cellstr如果数字和文本混在同一列整列会被迫转成文本型元胞数组。这个“自动推断”看着方便实际是把双刃剑大部分情况省事但遇到“大部分是数字偶尔一个‘待确认’”时整列会变成文本后续求均值直接报错。你可以用SelectedVariableNames只选需要的列避免输入矩阵过大T readtable(sales.xlsx, Sheet, Sheet1, Range, A1:D200, ... SelectedVariableNames, {月份, 销售额});其中Sheet指定工作表名Range使用Excel的A1风格区域SelectedVariableNames在已经确定前几行是变量名时按变量名筛选列。这里的“变量名”实际是Excel首行单元格内容如果首行有重复列名MATLAB会自动改成脚本体面的名称这个细节会在第5章展开。另外readtable会自动把空数值单元格设为NaN空文本单元格设为missing这在多数情况下是正确的。如果你不希望它“聪明”可以先读一个很小的范围确认推断结果没问题再扩大到全表。2.3 readmatrix 与 readcell两个“口味单一”的快读函数readmatrix专门为纯数值表格设计返回值是一个普通矩阵而不是tableM readmatrix(clean_data.xlsx, Sheet, Sheet2, Range, B2:E100);只要目标区域每个单元格都是数值readmatrix的读取效率很高内存占用也比table小很多。可一旦区域内出现一个文本单元格整列都会变成NaN且没有提示。因为矩阵本身只能存一种类型文本无法保留只能丢弃。所以readmatrix只适合“绝对干净”的数值表。readcell则完全不挑类型所有数据都放进元胞数组包括文本、数值、日期格式等C readcell(mixed.xlsx, Sheet, Sheet1, Range, A1:F50);readcell的好处是原样保存单元格适合拿来做数据体检比如逐格检查某个意外数值是怎么混进去的。缺点也很直接元胞数组处理起来不如table方便对单列数据取均值得先手动转成数值向量。这三个函数本质上是针对不同“形状”的数据写的readmatrix数值矩阵、readcell元胞数组、readtable表格。先把Excel表按“纯数值、混合表格、文本为主”分类选型就不会出错。2.4 选错函数时的典型特征如果你不确定自己选错了函数可以对照下面的现象自查读出来所有数值列都变成NaN多半是用了readmatrix而表里存在文本列读取后数据全部挤在第一个sheet里无法区分工作表是忘了传Sheet参数读出来的列名变成了Var1、Var2是ReadVariableNames默认行为与文件表头不一致数据总是差一行是因为readtable默认把首行当变量名而实际首行是标题或备注。这些特征本质上都源于读取函数对“表头存在性”和“类型统一性”的假设。尤其是readtable它默认Excel文件第一行是变量名。如果你的Excel前两行是一句中文标题再往下才是字段名就必须用ReadVariableNamesfalse再手动设置变量名。没有统一公式拿到文件后先readcell看一小块比猜参数效率高得多。3. 读取范围、多工作表和指定列把readtable用到顺手3.1 Sheet与Range参数从整表读取改成定点读取readtable默认读取指定Excel文件的第一个工作表整表但实际工作中一个工作表往往有几十列、上万行而真正关心的只有一角数据。每次全表读取既慢又容易引入无关区域的脏数据所以我一般会先把Range收窄。T readtable(project_data.xlsx, Sheet, Sheet3, Range, A1:D500);Sheet参数可以传工作表名也可以传索引。为了可读性我推荐传名称不过需要注意如果工作表名称是中文在字符串里直接写没问题但不要混用单双引号。Range参数支持A1:B10这种完整矩形区域也支持A1单格但很少用。如果你不确定区域边界可以用readcell快速探测首列最后一个非空行再回头设置Range。Range的一个隐藏好处是能避开表头上面的公司注释和Logo图片。Excel文件里常见的“首行大标题”在readtable眼里会被当成变量名导致后续所有列名错位。用RangeA2:F200就能直接跳过标题行这种情况下最好配合ReadVariableNamestrue表示第二行才是真正的变量名。3.2 批量读取多个Sheet用sheetnames做循环一个Excel文件里有多个结构相同的工作表时手动写多次readtable很蠢而且一旦增加Sheet就要改代码。新版本MATLAB提供了sheetnames函数可以直接拿到全部工作表名sheets sheetnames(project_data.xlsx); allData cell(length(sheets), 1); for i 1:length(sheets) allData{i} readtable(project_data.xlsx, Sheet, sheets(i)); end这里的sheets(i)是字符串数组元素readtable的Sheet参数可以接收字符串数组索引值。循环结束后allData是元胞数组每个元素是对应工作表的table。如果你希望把所有表按行拼接可以用vertcatmerged vertcat(allData{:});vertcat要求每个table的变量个数和变量名完全一致。如果不同Sheet的列顺序有一点点差异vertcat就会报错因此我习惯先检查width和variableNames。另外sheetnames返回的是工作表显示名称不是内部Sheet1这种代号所以不会出现错位。3.3 指定列、跳过列与自定义类型用detectImportOptions接管推断自动推断在大多数表格上够用但遇到“某列是文本数字另一列是日期还有两列是重复编号”时手动调整类型更可控。detectImportOptions可以读取文件的工作表内容和推断规则然后你再修改规则最后传给readtableopts detectImportOptions(sales.xlsx, Sheet, Sheet1); opts.SelectedVariableNames {月份, 销售额, 备注}; opts.VariableTypes {datetime, double, string}; T readtable(sales.xlsx, opts);detectImportOptions返回一个ImportOptions对象它包含了每一列的名称、类型、缺失值规则等。上面代码中SelectedVariableNames指定只读取三列VariableTypes指定这三列的目标类型。注意VariableTypes的顺序要和SelectedVariableNames一一对应否则会张冠李戴。如果只想修改某一列用setvartype更加直接opts detectImportOptions(sales.xlsx); opts setvartype(opts, {销售额}, double);setvartype的好处是只改指定列其他列继续走自动推断。这个方法在Excel里“销售额”一列是文本格式时特别有用因为你明明想当数值处理却总被推断成cellstr。指定为double后如果个别单元格确实无法转换读取阶段就会报错而不是默默变成NaN。3.4 多级表头和空白行怎么办多级表头在财报中很常见第一行是“一季度”第二行才是“销售额”两层表头叠在一起。直接用readtable会把第一行当变量名第二行变第一行数据整张表乱掉。我一般分两步先用readcell看前几行结构再决定Range起点。假设真正的表头在第2行数据从第3行开始可以这样读T readtable(finance.xlsx, Sheet, Sheet1, ... Range, A3:H400, ReadVariableNames, true);然后手动改名T.Properties.VariableNames {月份, 销售额, 成本};这种方法很笨但最可靠。ReadVariableNames参数默认是true它与Range的配合规则是读取时把Range首行当作变量名。如果Range里有空行readtable会保留为NaN或missing导致数据行数膨胀我通常会在设置Range前用readcell确认没有全空行尤其是最后几行容易混进一堆无效数据。4. 数据类型与格式陷阱日期、文本型数字、缺失值的规范化方案4.1 日期读进来是序列号先确认是Excel序号还是字符串Excel内部存储日期时通常是一个整数序列号比如2024年1月1日实际上是45292。当用readmatrix直接读取日期列得到的自然是一堆四万多五万多的数字看起来像乱码其实没读错只是没转换。要转回MATLAB日期可以使用dateValues readmatrix(dates.xlsx, Sheet, Sheet1, Range, B2:B100); realDates datetime(dateValues, ConvertFrom, excel);MATLAB的datetime函数支持ConvertFrom参数设为excel时会把Excel序列号转换为datetime数组。注意Excel的日期起点与MATLAB不完全一致但ConvertFrom已经处理了偏移所以不需要手动加减天数。如果用readtable读取情况会不同。新版MATLAB在部分场景下会自动把Excel日期识别成datetime但前提是detectImportOptions判定该列为日期类型。如果推断成double就需要用上面的方式转换。我建议先执行head(T)看一眼输出如果日期列是double而不是datetime马上手动转不要等到画图时才发现横轴全是数字。4.2 文本型数字看起来是数字一求平均就报错Excel单元格左上角有绿色小三角往往是“文本型数字”。这列数据肉眼看到的是123、456但底层是文本。readtable自动推断时有可能把整列推断成cellstr于是你用mean(T.销售额)会直接报错提示未定义操作符。解决思路是把文本转数值T.销售额 str2double(T.销售额);str2double接收元胞数组时能按元素转换无法转换的文本变成NaN。这里要注意如果T.销售额是字符串数组而不是元胞数组str2double也能处理但空字符串会变成0而不是NaN。若要区分“原本是缺数据”和“数字0”建议先检查有没有空串。还可以在读取阶段用setvartype强制指定为double让MATLAB在导入时完成转换opts detectImportOptions(pay.xlsx); opts setvartype(opts, 实付金额, double); T readtable(pay.xlsx, opts);如果某单元格是“待确认”这类非数字文本这种强制转换会让读取直接报错至少能让你一眼看到脏数据在哪一行。另一种方案是先读成文本再定位不能转换的位置。这里没有万能解但我通常先强制转换真报错了再回到元胞数组看数据。4.3 空单元格与缺失值NaN、missing与空字符串的差别Excel空单元格在不同函数里的表示不一样。readmatrix把空单元格当0还是NaN取决于文件格式和是否显式写0更常见的是数值列空单元格变成NaN。readtable中数值列空单元格为NaN文本列空单元格为missing字符串列则可能变成missing。三者的判断方式不同T table([1; NaN], [文本; missing]); ismissing(T.Var2) isnan(T.Var1)ismissing是通用判断能同时识别NaN、missing和空字符串这是最省事的。我强烈建议不要在Excel里用空格表示缺失值因为空格会被读成空字符串而不是missing后续用ismissing能识别空字符串但用isnan就会漏掉。如果你发现一列文本中有大量空字符串可以先统一替换为missingT.备注(T.备注 ) missing;替换后再调用ismissing就干净了。另外不要依赖fillmissing处理缺失值之前先检查是否类型匹配否则会把数值列和文本列一起拉下水。4.4 单元格内换行和特殊字符小心行数莫名变多Excel单元格支持AltEnter换行有时你以为是一个单元格但在readtable读进来后可能被拆成多行尤其是使用文本文件格式导入时。另一个坑是金额数字里带千分位逗号比如1,234readtable会把它当文本而不会自动去掉逗号。处理方法是尽量在Excel源头清理或者在读取后用正则表达式删除干扰字符T.金额 str2double(strrep(string(T.原始金额), ,, ));strrep是字符串替换把逗号去掉后再转数值。这个方案适用于英文千分位如果用户习惯用中文全角逗号也要先替换成全角转半角。单元格内换行比较麻烦因为它会破坏行对应关系我一般用readcell定位真正有换行的列再决定是保留还是清洗。如果换行符只是文本列的备注不影响数值列通常保留即可如果地址列里有换行在导出成csv时会导致行列错位这时建议把换行符替换为空格T.地址 strrep(string(T.地址), newline, );5. 常见问题与避坑读取报错、乱码、大文件卡死的排查路径5.1 报错“Unable to read file”八成不是数据问题现象readtable(D:\data\销售.xlsx)报错Unable to read file或提示找不到文件、无权访问。原因最常见的是Excel文件正被另一个进程打开占用或者路径中的反斜杠和中文目录在部分环境不被识别。解决先按照下面顺序排查filePath fullfile(D:, data, 销售.xlsx); disp(exist(filePath, file)) [~, sheets] xlsfinfo(filePath);exist返回2表示文件存在返回0说明路径或文件名错了。xlsfinfo能读到工作表信息说明文件可用。如果文件确实被Excel开着关闭Excel再跑一次。另一个隐蔽原因是文件名后缀名显示为.xlsx但实际是Excel 97-2003格式.xls这时需要把后缀统一改成.xls再读取。不要相信文件的显示扩展名用dir看一眼真实文件名最有把握。5.2 数值列变成全NaN先怀疑“脏数据区”现象表格看起来全是数字用readmatrix读取后M里整列NaN或readtable读出来列类型是cellstr。原因某个单元格存在肉眼没注意的文本比如单位“元”、空格、下划线、错乱字符。只要区域内混进一个不是数字的单元格readmatrix的整列结果就会被影响readtable则可能改变整列类型。解决先用readcell把原始区域完整读出来定位异常值C readcell(data.xlsx, Sheet, Sheet1, Range, B2:B500); nonNumeric cellfun((x) ~isnumeric(x), C); badRows find(nonNumeric); disp(C(badRows))cellfun逐个判断单元格是否为数值返回逻辑数组find找出异常行。看到具体内容后选择在Excel中清理或手动替换。这里最难查的是“看起来是空格”的字符比如全角空格、nbsp;用strtrim清理后再转数值。5.3 大文件读到头秃先看Excel文件本身再考虑分割读取现象20MB的xlsx文件readtable跑了五分钟还没结束MATLAB窗口一直显示“正忙”。原因xlsx本质是zip压缩包解析过程需要解压全部XMLExcel本身的公式缓存、格式定义也会让读取变慢。尤其是一个Sheet里有十几万行、几十列纯手工逐单元格解析很吃力。解决思路有三个步骤。第一步确认是否有必要读全表如果业务只需要几列用Range和SelectedVariableNames缩小范围。第二步把Excel另存为CSV格式再读取CSV纯文本读取速度远快于xlsxT readtable(large_data.csv);第三步如果CSV也有几百MB可以考虑按块读取。readtable本身不支持跳过任意行数但可以先读成datastoreds datastore(large_data.csv, TreatAsMissing, NA); T read(ds, 20000);datastore是处理大文本表的常用工具它每次读取指定行数适合分批处理。注意它不像readtable那样支持Range但能通过SelectedVariableNames指定列。在处理大文件前最好先用whos估算内存占用避免读进来直接内存溢出。5.4 中文列名和重名列名readtable给的神坑现象Excel首行有两个“金额”列readtable读完后变量名变成了金额和金额_1后续用T.金额引用却拿到第一列而第二列怎么都引不对。原因MATLAB运行变量名不能重复自动重命名是保护机制但重命名规则并不直观。解决读取后主动查看并重命名T.Properties.VariableNames T.Properties.VariableNames {金额A, 金额B};更保险的方式是在readtable前先手动指定变量名范围或读取后立即重命名。如果中文列名带有空格、减号或不规则字符T.列名这种点号语法会出错只能改用T.(列名)引用T.(销售金额元)这种情况最容易发生在从第三方系统导出的Excel中变量名千奇百怪。我一般把所有列名统一改为英文字段名避免后续脚本里到处写中文变量名既难排查又容易踩编码坑。5.5 COM/ActiveX方案能用但不要优先现象使用actxserver(Excel.Application)方式读取Excel感觉能完全控制Excel但脚本运行不稳定有时候能读出数据有时候进程卡死。原因通过COM接口启动了一个真实的Excel进程一旦代码异常终止这个进程会残留并占用文件。解决优先使用原生readtable和readmatrix只有遇到极其特殊的Excel格式、需要触发Excel公式计算后才能读取时才考虑COM方案并且要在finally中关闭进程e actxserver(Excel.Application); try e.Workbooks.Open(filePath); % 触发计算并读取 catch error(COM读取失败); finally e.Quit; delete(e); end这个方案在日常数据整理中几乎没必要碰到密码保护或复杂宏表格时与其在MATLAB里对抗Excel不如先手动另存为干净的xlsx。6. 进阶用法把读取Excel封装成可复用的函数6.1 封装函数并处理多Sheet读Excel最大的重复劳动是“找Sheet、找Range、设置类型”这三件事。我习惯封装成一个简单函数输入文件路径和Sheet名输出table并且自动处理文件不存在的情况。function T readExcelTable(filePath, sheetName) arguments filePath (1,1) string sheetName (1,1) string end if ~exist(filePath, file) error(文件不存在: %s, filePath); end T readtable(filePath, Sheet, sheetName); T.Properties.VariableNames matlab.lang.makeValidName(T.Properties.VariableNames); endarguments是MATLAB R2019b以后支持的参数校验语法这里限制输入必须是单个字符串。函数先用exist检查文件再用readtable读取最后用matlab.lang.makeValidName把所有列名转为合法MATLAB变量名避免中文和空格带来的后续问题。调用时只需要一行T readExcelTable(sales.xlsx, Sheet1);6.2 验证封装函数并控制Range封装只是第一步真正让读取稳定的关键是验证。我会强制在测试时打印前几行和变量类型确认没有意外assert(istable(T), 返回值不是table); head(T) summary(T)summary能直观看到每列的类型和缺失值数量这一步能发现很多自动推断问题时在传输过程中被掩盖的细节。从那以后我每次拿到新Excel文件都强制走一遍“看形状、选函数、验类型、查缺失”的流程不再因为急着读取数据而跳过体检。希望这篇文章里的方法和避坑记录也能帮你把MATLAB读取Excel这件事从“总是出问题”变成“一次读对”。本文还有配套的精品资源点击获取