Javascript to Excel:由于缺乏"range"方法而性能不佳



考虑到您只使用Internet Explorer(在大型企业中通常是这样),您得出的结论是,您可以为用户提供将HTML网格视图转换为Excel文件的可能性:此外,您只需考虑到,只要用户要求,您就必须这样做…

我第一次从外部将表(或数组)写入Excel是使用Visual Basic(.net的服务器端)

1) 我使用的第一种方法乍一看似乎很好,顺便说一句,它很简单:在行上的循环中设置列上的循环,并将VB数组中的每个值写入Excel表。因此:

        Dim j, k as Integer
        Dim Valeur as String
        'let us suppose the VB 2D-array is "Tab(10,20)", containing 11 rows of 21 columns of strings
        'let us suppose the upper left corner of the Excel range is line 7, column 3:
        For j = 0 to 10
           For k = 0 to 20
             Valeur = Tab(j, k)
             Cells(j + 7, k + 3).Value = valeur
           Next
        Next

2) 在编程了上面的方法后,我最终意识到,尽管它简单而合乎逻辑,但它是一个糟糕的方法,原因只有一个:它非常慢所以我找到了一个更好的方法,包括一次写入整个单元格范围:

                Feuil.Range("C7:W17").Value = Tab

第一种方法和第二种方法有什么区别?好吧,这两种方法都能正常工作,但如果你考虑一个由300行20列(或6000个单元格)组成的表,第一种方法所需的时间大约为1分钟,而第二种方法只需半秒!

因此,当谈到JavaScript时,我尝试了同样的方法:首先,打开一个Excel ActiveX对象(当然是在MS-IE中),它可以访问Excel对象模型引用(http://msdn.microsoft.com/en-us/library/bb149081(v=office.12).aspx),使用名为"ap"的对象中的CSV堆栈集:

   // 'ap' is a Javascript object holding a table of CSV strings (natural index: 1..n)
   var valCell;         
   var lim = ap.nbChamps;  // 'nbChamps'= number of csv columns in 'ap' object        
   var curLig = 6;         // the datas are written to lines 7 and under        
   for (var j = 1; j <= ap.nbelem; j++) // ap.nbelem= number of lines in 'ap'
   {   // lines loop            
      curLig += 1;            
      for (var k = 1; k <= lim; k++)  // N.B: 'ap' uses natural index: 1 to n and not 0 to n-1
      {   // columns loop                
        valCell = ap.litEnLC(j, k);  // 'ap' method reading column k from line j              
        classeur.ActiveSheet.Cells(curLig, k + 2 ).value = valCell;                              
      }        
    } 

使用该方法后,我再次发现同样的缓慢:因此,我想将第二个方法转换为javascript,如下所示:。首先,向"ap"对象添加一个方法,该方法将CSV堆栈转换为Javascript 2D数组。其次,将这个2D数组写入"range"对象中,就像我在Visual Basic中所做的那样。因此:

    // 'zone' is the range. For example: zone= "C7:W17"
    var biTab = ap.pcttEnTab(); // converts CSV stack into a 2D-array
    classeur.ActiveSheet.Range(zone).value = biTab;  

正如预期的那样,这会更快,但问题是它并没有真正起作用,因为它没有将2D数组的每个值转移到Excel范围的相应单元格,而是在Excel范围的每个单元格中写入整个Javascript 2D数组

所以问题是:如何一次将Javascript 2D数组写入Excel范围?

感谢任何能给我答案的人。。。

顺便说一句,我添加了pcttEnTab方法,以防有人可以用这种方法来解释我的问题:

this.pcttEnTab = function ()    // Array (tableau à 2 dimensions)
{   // convertit la pile PCTT en tableau à 2 dimensions         
    var j, k, s;
    var biTab = new Array();
    for (k = 0; k < this.nbelem; k++) // create a columns Array for each line
    {
        biTab[k] = new Array();
    }
    for (j = 1; j <= this.nbelem; j++)  // lines loop (natural index)
    {
        for (k = 1; k <= this.nbChamps; k++) // columns loop
        {
            s = this.litEnLC(j, k);
            biTab[j - 1][k - 1] = s;
        }
    }
    return biTab
}

您需要将JavaScript数组转换为本机数组。一种方法是使用Dictionary对象,请参阅http://cwestblog.com/2011/10/24/javascript-snippet-array-prototype-tovbarray:

var dict = new ActiveXObject('Scripting.Dictionary');
for (var i=0;i < 5; i++ ) dict.add(i,i);
sheet.cells(1,1).resize(5, 1).value = sheet.application.Transpose(dict.items());

如果写入一行,请提交Transpose()

看看微软的这篇有趣的文章,它解释了ActiveSheet.Range和JavaScript数组之间的一些交互。他们提到了"使用SafeArray的解决方法"。。。也许这会有所帮助。

最新更新