1

问题:

我正在使用 jqGrid 来显示表格。
但是,如果 Internet Explorer 9 和 8 必须显示超过 20 行,则性能不佳...

我已经尝试过 SlickGrid,它在 Internet Explorer 中的性能似乎对我来说要好得多。

我现在唯一阻止我切换到 SlickGrid 的问题是,使用 SlickGrid,您不能只是从 SlickGrid 复制粘贴一系列单元格以正确处理。

复制粘贴转置单元格,以便列是行,行是列(好吧,我知道你可以在 excel 中转回,但我不是普通的最终用户。此外,必须这样做是恼人的) ...

使用 jqGrid,这可以完美地工作。
请注意,我明确不想将数据输出为 CSV/XLS/XLSX 文件。

任何人都知道如何正确地将 SlickGrid 复制粘贴到 Excel(非转置)?

4

2 回答 2

2

看到这个插件: http: //labs.nereo.fr/slick.html

但它有3个问题,A.无法正确粘贴到excel,B.粘贴到SlickGrid时会破坏一个额外的单元格C.当源范围大于目标时出现错误

我做了一些改变来解决它们。见下文:

(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "CellExternalCopyManager": CellExternalCopyManager
    }
  });


  function CellExternalCopyManager(options) {
    /*
      This manager enables users to copy/paste data from/to an external Spreadsheet application
      such as MS-Excel® or OpenOffice-Spreadsheet.

      Since it is not possible to access directly the clipboard in javascript, the plugin uses
      a trick to do it's job. After detecting the keystroke, we dynamically create a textarea
      where the browser copies/pastes the serialized data. 

      options:
        copiedCellStyle : sets the css className used for copied cells. default : "copy-manager"
        dataItemColumnValueExtractor : option to specify a custom column value extractor function

    */
    var _grid;
    var _self = this;
    var _copiedRanges;
    var _options = options || {};
    var _copiedCellStyle = _options.copiedCellStyle || "copy-manager";


    var keyCodes = {
      'C':67,
      'V':86
    }

    function init(grid) {
      _grid = grid;
      _grid.onKeyDown.subscribe(handleKeyDown);      
    }

    function destroy() {
      _grid.onKeyDown.unsubscribe(handleKeyDown);
    }

    function getDataItemValueForColumn(item, columnDef) {
      if (_options.dataItemColumnValueExtractor) {
        return _options.dataItemColumnValueExtractor(item, columnDef);
      }
      return item[columnDef.field];
    }

    function setDataItemValueForColumn(item, columnDef, value) {
      if (_options.dataItemColumnValueSetter) {
        return _options.dataItemColumnValueSetter(item, columnDef, value);
      }
      return item[columnDef.field] = value;
    }


    function _createTextBox(innerText){
      var ta = document.createElement('textarea');
      ta.style.position = 'absolute';
      ta.style.left = '-1000px';
      ta.style.top = '-1000px';
      ta.value = innerText;
      document.body.appendChild(ta);
      document.designMode = 'off';
      ta.focus();

      return ta;
    }
    function _decodeTabularData(_grid, ta){
      var columns = _grid.getColumns();
      var clipText = ta.value;
      var clipRows = clipText.split("\r\n"); 
     var clippeds = [];

      document.body.removeChild(ta);

      for (var i=0; i<clipRows.length; i++) {
        if (clipRows[i]!="") // get rid of the last ""
          clippeds[i] = clipRows[i].split(String.fromCharCode(9)); //  "\t" 
      }

      var selectedCell = _grid.getActiveCell();
      var activeRow = selectedCell.row + pageSize*pageNum;// getActiveCell.row starts from 0  for each page.
      var activeCell = selectedCell.cell;
      var desty = activeRow;
      var destx = activeCell;

      var data = _grid.getData().getItems();  

      for (var y = 0; y < clippeds.length; y++){
        for (var x = 0; x < clippeds[y].length; x++){
            var desty = activeRow + y;
          var destx = activeCell + x;
            if (desty < data.length && destx < grid.getColumns().length ) { 
                data[desty][columns[destx].field] = clippeds[y][x];
            if ( data[desty].hasOwnProperty('id')) 
              changedIds.push(data[desty].id);// record changed id used by saving function
          }
        }
      }

      _grid.invalidate();
    }


    function handleKeyDown(e, args) {
      var ranges;
      if (!_grid.getEditorLock().isActive()) {

        //ESC
        if (e.which == $.ui.keyCode.ESCAPE) {
          if (_copiedRanges) {
            e.preventDefault();
            clearCopySelection();
            _self.onCopyCancelled.notify({ranges: _copiedRanges});
            _copiedRanges = null;
          }
        }

        if (e.which == keyCodes.C && (e.ctrlKey || e.metaKey)) {    // CTRL + C
          ranges = _grid.getSelectionModel().getSelectedRanges();

          if (ranges.length != 0) {
            _copiedRanges = ranges;
            markCopySelection(ranges);
            _self.onCopyCells.notify({ranges: ranges});

            var columns = _grid.getColumns();
            var clipText = "" ;
            for (var rg = 0; rg < ranges.length; rg++){
                var range = ranges[rg];
                for (var i=range.fromRow; i< range.toRow+1 ; i++){
                    var dt = _grid.getDataItem(i);
                    for (var j=range.fromCell; j< range.toCell+1 ; j++){
                          if (j==range.fromCell) 
                            clipText = clipText.concat(getDataItemValueForColumn(dt, columns[j]));
                          else 
                          clipText = clipText.concat("\t",getDataItemValueForColumn(dt, columns[j]));
                    }
                    clipText = clipText.concat("\r\n");
                }
            }

            var ta = _createTextBox(clipText);


            $(ta).select();
            setTimeout(function(){
                document.body.removeChild(ta);
            }, 100);

            return false;
          }
        }

        if (e.which == keyCodes.V && (e.ctrlKey || e.metaKey)) {    // CTRL + V
            var ta = _createTextBox(''); 

            setTimeout(function(){ 
                _decodeTabularData(_grid, ta);
            }, 100);

            return false;
        }
      }
    }

    function markCopySelection(ranges) {
      var columns = _grid.getColumns();
      var hash = {};
      for (var i = 0; i < ranges.length; i++) {
        for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
          hash[j] = {};
          for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
            hash[j][columns[k].id] = true;
          }
        }
      }
      _grid.setCellCssStyles(_copiedCellStyle, hash);
    }

    function clearCopySelection() {
      _grid.removeCellCssStyles(_copiedCellStyle);
    }

    $.extend(this, {
      "init": init,
      "destroy": destroy,
      "clearCopySelection": clearCopySelection,

      "onCopyCells": new Slick.Event(),
      "onCopyCancelled": new Slick.Event(),
      "onPasteCells": new Slick.Event()
    });
  }
})(jQuery);
于 2012-08-27T08:52:13.570 回答
0

李东,谢谢!您的代码帮助了我,但我发现使用 labs.nereo.fr 版本的函数 handleKeyDown 更快。

(function ($) {
    // register namespace$.extend(true, window, {
        "Slick": {
          "CellExternalCopyManager": CellExternalCopyManager
        }
    });


function CellExternalCopyManager(options) {
/*
  This manager enables users to copy/paste data from/to an external Spreadsheet application
  such as MS-Excel® or OpenOffice-Spreadsheet.

  Since it is not possible to access directly the clipboard in javascript, the plugin uses
  a trick to do it's job. After detecting the keystroke, we dynamically create a textarea
  where the browser copies/pastes the serialized data. 

  options:
    copiedCellStyle : sets the css className used for copied cells. default : "copy-manager"
    dataItemColumnValueExtractor : option to specify a custom column value extractor function

*/
var _grid;
var _self = this;
var _copiedRanges;
var _options = options || {};
var _copiedCellStyle = _options.copiedCellStyle || "copied";
var _clearCopyTI = 0;


var keyCodes = {
  'C':67,
  'V':86
}

function init(grid) {
  _grid = grid;
  _grid.onKeyDown.subscribe(handleKeyDown);      
}

function destroy() {
  _grid.onKeyDown.unsubscribe(handleKeyDown);
}

function getDataItemValueForColumn(item, columnDef) {
  if (_options.dataItemColumnValueExtractor) {
    return _options.dataItemColumnValueExtractor(item, columnDef);
  }
  return item[columnDef.field];
}

function setDataItemValueForColumn(item, columnDef, value) {
  if (_options.dataItemColumnValueSetter) {
    return _options.dataItemColumnValueSetter(item, columnDef, value);
  }
  return item[columnDef.field] = value;
}


function _createTextBox(innerText){
  var ta = document.createElement('textarea');
  ta.style.position = 'absolute';
  ta.style.left = '-1000px';
  ta.style.top = '-1000px';
  ta.value = innerText;
  document.body.appendChild(ta);
  document.designMode = 'off';
  /* Изменяем фокус на select. Сделали это, чтобы после каждого копирования скорость таблицы не уменьшалась (см. ниже). 
  ta.focus();
  */
  ta.select()
  return ta;
}
function _decodeTabularData(_grid, ta){
  var columns = _grid.getColumns();
  var clipText = ta.value;
  var clipRows = clipText.split("\r\n"); 
 var clippeds = [];

  document.body.removeChild(ta);

  for (var i=0; i<clipRows.length; i++) {
    if (clipRows[i]!="") // get rid of the last ""
      clippeds[i] = clipRows[i].split(String.fromCharCode(9)); //  "\t" 
  }

  var selectedCell = _grid.getActiveCell();
  /* Переменную activeRow зануляем (что за переменные pageSize и PageNum - непонятно)
  var activeRow = selectedCell.row + pageSize*pageNum;// getActiveCell.row starts from 0  for each page.
  */
  var activeRow = null;
  var activeCell = selectedCell.cell;
  var desty = activeRow;
  var destx = activeCell;
  var changedIds = []; // Устанавливаем переменную changedIds
  var data = _grid.getData().getItems();  

  for (var y = 0; y < clippeds.length; y++){
    for (var x = 0; x < clippeds[y].length; x++){
        var desty = activeRow + y;
      var destx = activeCell + x;
        if (desty < data.length && destx < grid.getColumns().length ) { 
            data[desty][columns[destx].field] = clippeds[y][x];
        if ( data[desty].hasOwnProperty('id')) 
          changedIds.push(data[desty].id);// record changed id used by saving function
      }
    }
  }

  _grid.invalidate();
}

function handleKeyDown(e, args) {
  var ranges;
  if (!_grid.getEditorLock().isActive() || _grid.getOptions().autoEdit) {
    if (e.which == keyCodes.ESC) {
      if (_copiedRanges) {
        e.preventDefault();
        clearCopySelection();
        _self.onCopyCancelled.notify({ranges: _copiedRanges});
        _copiedRanges = null;
      }
    }

    if (e.which == keyCodes.C && (e.ctrlKey || e.metaKey)) {    // CTRL + C
      ranges = _grid.getSelectionModel().getSelectedRanges();
  if (ranges.length != 0) {
        _copiedRanges = ranges;
        markCopySelection(ranges);
        _self.onCopyCells.notify({ranges: ranges});

        var columns = _grid.getColumns();
        var clipText = "";
    for (var rg = 0; rg < ranges.length; rg++){
            var range = ranges[rg];

    var clipTextRows = [];
    if (clipText == "" && _options.includeHeaderWhenCopying) {
        var clipTextHeaders = [];
        for (var j = range.fromCell; j < range.toCell + 1 ; j++) {
            if (columns[j].name.length > 0)
                clipTextHeaders.push(columns[j].name);
        }
        clipTextRows.push(clipTextHeaders.join("\t"));
    }

            for (var i=range.fromRow; i< range.toRow+1 ; i++){
                var clipTextCells = [];
                var dt = _grid.getDataItem(i);

                for (var j=range.fromCell; j< range.toCell+1 ; j++){
                    clipTextCells.push(getDataItemValueForColumn(dt, columns[j]));
                }
                clipTextRows.push(clipTextCells.join("\t"));
            }
            clipText += clipTextRows.join("\r\n") + "\r\n";
        }
        var ta = _createTextBox(clipText);
        return false;
      }
    }
  }
}


function markCopySelection(ranges) {
  var columns = _grid.getColumns();
  var hash = {};
  for (var i = 0; i < ranges.length; i++) {
    for (var j = ranges[i].fromRow; j <= ranges[i].toRow; j++) {
      hash[j] = {};
      for (var k = ranges[i].fromCell; k <= ranges[i].toCell; k++) {
        // hash[j][columns[k].id] = true;
    // Применяем стиль для скопированных ячеек
    hash[j][columns[k].id] = _copiedCellStyle;
      }
    }
  }
  _grid.setCellCssStyles(_copiedCellStyle, hash);
  clearTimeout(_clearCopyTI);
  _clearCopyTI = setTimeout(function(){
    _self.clearCopySelection();
  }, 400);
}

function clearCopySelection() {
  _grid.removeCellCssStyles(_copiedCellStyle);
}

$.extend(this, {
  "init": init,
  "destroy": destroy,
  "clearCopySelection": clearCopySelection,

  "onCopyCells": new Slick.Event(),
  "onCopyCancelled": new Slick.Event(),
  "onPasteCells": new Slick.Event()
});
}
})(jQuery);
于 2015-07-13T07:33:00.887 回答