【问题标题】:Using ActiveX to Import from Excel to Matlab使用 ActiveX 从 Excel 导入 Matlab
【发布时间】:2018-04-14 12:10:27
【问题描述】:

我需要优化 .xls 文件到 matlab 的导入,因为 xlsread 处理大量文件非常耗时。当前xlsread脚本如下:

scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);    
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
xlsimportdata = zeros(7,6,xlscount);

for k = 1:xlscount
xlsimport = xlsread(xlsnames(k).name,'D31:I37');
xlsimportdata(:,1:size(xlsimport,2),k) = xlsimport;
end

我每周有近 10,000 个文件需要处理,大约需要处理。在我当前的工作站上处理每个文件需要 2 秒,大约需要 5½ 小时。

我已经读到 ActiveX 可以用于此目的,但这远远超出了我目前的编程技能,并且无法在其他地方找到解决方案。任何有关如何做到这一点的帮助将不胜感激。

如果使用 ActiveX(或其他建议的方法)执行起来很简单,我也会对单元格 D5 和 G3 上的数据感兴趣,我目前正在从 'xlsnames(k,1).name' 和 'xlsnames (k,1).date'

编辑:更新以反映解决方案

% Get path to .m script
scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);

% Generate list of .xls file data
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
SampleInfo = cell(xlscount,2);
xlsimportdata = cell(7,6,xlscount);

% Define xls data ranges to import
SampleID = 'G3';
SampleRuntime = 'D5';
data_range = 'D31:I37';

% Initiate progression bar
h = waitbar(0,'Initiating import...');

% Start actxserver
exl = actxserver('excel.application');
exlWkbk = exl.Workbooks;

for k = 1:xlscount

    % Restart actxserver every 100 loops due limited system memory
    if mod (k,100) == 0
        exl.Quit
        exl = actxserver('excel.application');
        exlWkbk = exl.Workbooks;
    end

    exlFile   = exlWkbk.Open([dname filesep xlsnames(k).name]);
    exlSheet1 = exlFile.Sheets.Item('Page 0');

    rngObj1    = exlSheet1.Range(SampleID);
    xlsimport_ID = rngObj1.Value;

    rngObj2    = exlSheet1.Range(SampleRuntime);
    xlsimport_Runtime = rngObj2.Value;

    rngObj3    = exlSheet1.Range(data_range);
    xlsimport_data = rngObj3.Value;

    SampleInfo(k,1) = {xlsimport_ID};
    SampleInfo(k,2) = {xlsimport_Runtime};
    xlsimportdata(:,:,k) = xlsimport_data;

    % Progression bar updater
    progress = round((k / xlscount) * 100);

    importtext = sprintf('Importing %d of %d', k, xlscount);
    waitbar(progress/100,h,sprintf(importtext));
    disp(['Import progress: ' num2str(k) '/' num2str(xlscount)]);

end
%close actxserver
exl.Quit

% Close progression bar
close(h)

【问题讨论】:

  • ActiveX 还需要打开和关闭 10K 文件,我不确定它是否会节省时间。如果您可以将数据存储在较少数量的文件中,在单独的工作表中,则可以大大加快这两种方法的速度。如果没有,请考虑这个 fex-@​​987654321@
  • 不幸的是,我没有该选项可用。用于导入 matlab 的 .xls 文件是从在生产和实验室的工作站上运行的第 3 方软件自动生成的报告文件。
  • 不用像xlsread 那样每次读取文件时都打开和关闭 Excel,从而节省大量时间。有关示例,请参阅here。实际上,这是通过直接操作 ActiveX 代理来完成的。我有自己的功能,但我现在没有。

标签: excel matlab import activex import-from-excel


【解决方案1】:

试试这个。无论如何,我都不是 ActiveX Excel 专家。但是,这适用于我的少量测试 XLS 文件 (3)。我从来没有closeexlWkbk,所以我不知道内存使用是否正在增加,或者它是否在下一个在其位置打开后在 descoped 时自动清理......所以使用风险自负。我看到速度几乎提高了 2.5 倍,这似乎很有希望。

>> timeit(@getSomeXLS)
ans =
    1.8641

>> timeit(@getSomeXLS_old)
ans =
    4.6192

如果这适用于大量 Excel 工作表,请留下一些反馈,因为我很好奇它是如何进行的。

function xlsimportdata = getSomeXLS()

scriptName = mfilename('fullpath');
[currentpath, filename, fileextension]= fileparts(scriptName);
xlsnames = dir(fullfile(currentpath,'*.xls'));
xlscount = length(xlsnames);
xlsimportdata = zeros(7,6,xlscount);
exl = actxserver('excel.application');

exlWkbk = exl.Workbooks;
dat_range = 'D31:I37';

for k = 1:xlscount
    exlFile   = exlWkbk.Open([currentpath filesep xlsnames(k).name]);    
    exlSheet1 = exlFile.Sheets.Item('Sheet1'); %Whatever your sheet is called.
    rngObj    = exlSheet1.Range(dat_range);
    xlsimport = cell2mat(rngObj.Value);
    xlsimportdata(:,:,k) = xlsimport;
end
exl.Quit

【讨论】:

  • 这个解决方案效果很好。对 100 个文件进行了测试,发现速度提高了 3.85 倍(177 秒 xlsread 与 46 秒 activex)。我没有遇到任何内存使用问题。在具有 8GB 内存的 i5-5300U 上运行脚本
  • 我需要修改该评论。导入期间内存使用量不断增加,因此如果用于数百个文件,则需要解决此问题。
  • 也许每 100 次迭代或者无论多少次都适合内存调用退出并重新启动 actxserver?就像我说的那样,我不能 100% 确定何时清除内存,但值得一试。在循环内添加if mod (k,100) == 0exl.quit 等内容。我在移动设备上,所以现在无法尝试任何东西。
  • 我做了一个类似的实现,虽然不太优雅;)relaunch = isa(k/100,'int32'); if relaunch == 1 exl.Quit exl = actxserver('excel.application'); exlWkbk = exl.Workbooks;
猜你喜欢
  • 1970-01-01
  • 2017-07-01
  • 2014-12-03
  • 2023-03-09
  • 2015-08-05
  • 2012-06-02
  • 1970-01-01
  • 2013-10-16
  • 1970-01-01
相关资源
最近更新 更多