【问题标题】:write information into Excel after each loop每次循环后将信息写入 Excel
【发布时间】:2011-10-03 14:42:10
【问题描述】:

我有一个 6x7 矩阵(A),我正在对它进行一些操作,用于 k=1:50(循环数)。 我知道为了在 excel 文件中写入单个矩阵,我需要:

xlswrite('Filename.xls', A, 'A1')

如何在每个循环之后写入信息,这样每个循环都从 Excel 中的位置 A1+((k-1)*6+1) 开始,并且我列出了 Matrix(A) 的所有结果一个接一个。

谢谢!

【问题讨论】:

    标签: excel matlab file-io matrix


    【解决方案1】:

    使用XLSWRITE 函数时,您可以避免每次都计算 Excel 单元格范围,方法是同时指定工作表编号和范围,其中范围仅给出第一个单元格开始的位置。

    如果矩阵每次迭代都改变大小,这将特别有用;我们只需取最后一个使用的单元格并将其移动矩阵的行数。

    例子:

    offset = 1;
    for i=1:5
        %# generate different size matrices each loop
        A = ones(randi(4),randi(4)).*i;
    
        %# insert matrix in Excel inside the 1st sheet, starting at cell specifed
        xlswrite('filename.xls', A, 1, sprintf('A%d',offset));
    
        %# increment offset
        offset = offset + size(A,1);
    end
    

    这将创建一个包含以下内容的 Excel 文件:

    1    1        
    1    1        
    1    1        
    2    2    2    2
    3    3
    3    3
    4            
    4            
    4            
    4            
    5    5    5    
    5    5    5    
    5    5    5    
    5    5    5    
    

    请注意,每次调用 XLSWRITE 时都会与 Excel 建立连接,然后关闭。这有很大的开销。

    更好的方法是打开 Excel 一次,然后重复使用同一个会话来写入所有数据,然后在完成后关闭它。但是,您必须自己调用 Office 互操作函数。

    由于我上面提到的技巧现在不起作用,我将使用 "Calculate Excel Range" 函数来计算单元格范围(FEX 还有许多其他实现)。

    这是代码(重复使用来自previous answer 的一些代码):

    %# output file name
    fName = fullfile(pwd, 'file.xls');
    
    %# create Excel COM Server
    Excel = actxserver('Excel.Application');
    Excel.Visible = true;
    
    %# delete existing file
    if exist(fName, 'file'), delete(fName); end
    
    %# create new XLS file
    wb = Excel.Workbooks.Add();
    wb.Sheets.Item(1).Activate();
    
    %# iterations
    offset = 0;
    for i=1:50
        %# generate different size matrices each loop
        A = ones(randi(4),randi(4)).*i;
    
        %# calculate cell range to fit matrix (placed below previous one)
        cellRange = xlcalcrange('A1', offset,0, size(A,1),size(A,2));
        offset = offset + size(A,1);
    
        %# insert matrix in sheet
        Excel.Range(cellRange).Select();
        Excel.Selection.Value = num2cell(A);
    end
    
    %# save XLS file
    wb.SaveAs(fName,1);
    wb.Close(false);
    
    %# close Excel
    Excel.Quit();
    Excel.delete();
    

    事实上,我用 50 次迭代运行了这两个版本,并将时间与 TIC/TOC 进行了比较:

    Elapsed time is 68.965848 seconds.      %# calling XLSWRITE
    Elapsed time is 2.221729 seconds.       %# calling Excel COM directly
    

    【讨论】:

    • 我确信这应该可行,但这就是我得到的报告:未定义函数或方法 'actxserver' 用于类型为“char”的输入参数。 ==> Deux_1 中的错误 9 Excel = actxserver('Excel.Application');
    • 另外,我想提一下我有Macintosh,不知道这是否影响程序?!
    • @kojikurac:COM/ActiveX 技术不适用于 Mac,因此第二种解决方案仅适用于 Windows。此外,根据此页面,我认为 XLSWRITE 回退到在 Mac 和 Linux 上使用 CSV 格式:mathworks.com/support/solutions/en/data/1-2SJUON/…。所以要么在 Windows 机器上运行代码,要么切换到另一种文件格式来导出数据(可能是简单的文本文件)......
    • Buhu :(有没有办法使用这种文本格式以便 Excel 可以读取它们?
    • @kojikurac:只要坚持使用 CSV 文件,它们只是简单的文本文件(每行的值以逗号分隔),而且 Excel 可以识别它们。您可以在 SO 上搜索如何使用 CSV 的示例:stackoverflow.com/questions/tagged/matlab+csv
    【解决方案2】:

    我认为xlswrite 会覆盖现有文件,因此您最好收集所有数据,然后一次性写入。此外,一次编写所有内容会更快,因为它只涉及打开和关闭 Excel 一次。

    但是,如果您真的想在循环中编写它,以下应该可以工作(假设您的意思是向下):

    range = sprintf('A%i:G%i', (k-1)*6+[1 6]);
    xlswrite('Filename.xls', A, range);
    

    请注意,如果 A 改变大小,这不会自动调整。

    【讨论】:

    • ???在输入数组的 156 维使用 ==> xlswrite 时出错,输入数组的维数不能大于 2。 ==> Trois_3 在 77 xlswrite('MatlabExcel.csv', M, start) 出错
    • 那个错误信息意味着 ndims(M) > 2。我还检查了xlswrite 命令的语法,范围规范不正确,所以我现在更新一下.请注意,代码旨在在循环内运行。
    • 除了覆盖之外,您可能希望一次性写入,因为每次写入时都需要打开和关闭 excel,这会在您的迭代中引入巨大的开销。
    • 同意。我会将其添加到答案中。
    猜你喜欢
    • 2022-01-07
    • 2012-10-20
    • 2022-10-05
    • 2019-08-18
    • 1970-01-01
    • 2021-04-08
    • 2016-10-21
    • 2020-01-05
    • 2017-01-04
    相关资源
    最近更新 更多