使用 ActiveX 从 Excel 导入到 Matlab

Using ActiveX to Import from Excel to Matlab

我需要优化 .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

我每周有近 10k 个文件需要处理,大约有 10000 个文件需要处理。在我当前的工作站上处理每个文件 2 秒,大约需要 5.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 Excel 专家。但是,这适用于我的少量测试 XLS 文件 (3)。我从来没有 close exlWkbk 所以我不知道内存使用是否正在增加,或者在下一个打开后它是否自动清理了......所以使用风险自负。我看到速度提高了近 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