2

カレンダーからイベントの詳細を取得してスプレッドシートの列AとBに追加し、重複するイベントを削除して、日付に基づいて並べ替えるスクリプトを使用しています。私の希望は、スタッフにこれらのイベントに関する追加データを列C、Dなどに追加してもらうことです。

これは正常に機能しているようですが、C、D列に情報が追加されると、インポートされているコンテンツだけでなく行全体を比較しているため、スクリプトの重複排除機能は機能しなくなります。

行が重複していて削除する必要があるかどうかを判断するときに、列AとBのみをチェックするように、以下の重複排除スクリプトを調整する方法はありますか?

この記事のバリエーションセクションにある以下のコード(現在コメントアウトされている)調整を使用しようとしました:https ://developers.google.com/apps-script/articles/removing_duplicates-それでも機能しないようです。

助けてくれてありがとう

スクリプト:

enter code here

//this section retrieves the information from a calendar from a user submitted date until the end of the year

function importEvents(){
  var calID = Browser.inputBox("Please enter your google Cal ID", Browser.Buttons.OK_CANCEL);
  var startdate = Browser.inputBox("Start date using 1/1/2013 format", Browser.Buttons.OK_CANCEL);
  var cal = CalendarApp.getCalendarById(calID);
  var events_sheet = SpreadsheetApp.getActiveSheet();
  var events = cal.getEvents(new Date(startdate), new Date("1/1/2014"));
  var lr = events_sheet.getLastRow();
  var eventarray = new Array();

  var i = 0; // edited
    for (i = 0; i < events.length; i++) {
      line = new Array();
      line.push(events[i].getStartTime());
      line.push(events[i].getTitle());

     //Potential more data that I am not getting at this time
     // line.push(events[i].getDescription());
     // line.push(events[i].getEndTime());

      eventarray.push(line);
    }

    events_sheet.getRange("A"+(lr+1)+":B"+(lr+i)).setValues(eventarray);

  //sort ascending dy date

  var range = SpreadsheetApp.getActiveSheet().getRange("A3:F2000"); 
  range.sort([{column: 1, ascending: true}]); 

  //removes duplicate rows

  var sheet = SpreadsheetApp.getActiveSheet();
  var data = sheet.getDataRange().getValues();
  var newData = new Array();
  for(i in data){
    var row = data[i];
    var duplicate = false;
    for(j in newData){

      if(row.join() == newData[j].join()){
  duplicate = true;

   //This was supposed to only check the first 2 columns, but it doesn't work
   //I found this code in the variation section of this tutorial: https://developers.google.com/apps-script/articles/removing_duplicates   
   //     
   //  if(row[0] == newData[j][0] && row[1] == newData[j][1]){
   // duplicate = true;

      }
    }
    if(!duplicate){
      newData.push(row);
    }
  }
  sheet.clearContents();
  sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData);

}
4

2 に答える 2

3

コメントアウトされたブロックは、微調整を加えることで機能させることができます。データの性質と、チュートリアルでオブジェクトの比較が機能する方法が考慮されていなかったために、問題が発生します。( JavaScriptの日付オブジェクトの比較を参照してください。)

最初の列はDateオブジェクトで構成されており、コンパレータは、比較の両側が同じオブジェクト==である場合にのみ評価します。行全体の比較では、操作によって日付が文字列に強制変換されています。次のように、セルごとに同じ効果を得ることができます。true.join()

 if(row[0].toString() == newData[j][0].toString() && row[1] == newData[j][1]){
   duplicate = true;
 }

または、操作を使用して、比較を最初の2つの列に制限することもできますArray.slice().join()このように、比較用の文字列を形成するために引き続き使用するため、比較されているタイプを知る必要はありません。

if(row.slice(0,2).join() == newData[j].slice(0,2).join()){
  duplicate = true;
}

並べ替え

遭遇するもう1つの問題は、の配置ですrange.sort()。重複を削除する前に並べ替えるのは危険です。これは、新しく取得されたイベントデータと、追加の情報列がある可能性のある同じイベントのデータの順序を保証できないためです。その結果、重複した削除により、ユーザーが入力した情報が消去される可能性があります。並べ替えを最終ステップのままにするか、並べ替えに追加の列を含めて順序を保証する方が安全です。

もう1つの小さな問題:を使用すると.getRange("A3:F2000")、スプレッドシートが2000行に拡張されるという副作用があります。代わりにを使用することもできます.getRange("A3:F")。これにより、最大範囲を拡張せずに取得できます。

ただし、完全にjavascript配列を使用して並べ替えを行うことをお勧めします。これは、スプレッドシートサービスを使用するよりもはるかに高速です。からソートしていたので、シートの上部に保持したい2行のヘッダー情報があると想定していますA3。並べ替えを行う方法は次のとおりです。

// sort ascending by date - retain header lines
var headers = newData.slice(0,2);
var sorted = newData.slice(2).sort(sortFunction);
var newData = headers.concat(sorted);

どこsortFunction()にありますか:

function sortFunction( a, b ) {
  // coerce dates to numbers and return comparison
  return ((+a[0]) - (+b[0]))
}

最終スクリプト

上記の変更を加えて、次のようになります。

function importEvents(){
  var calID = Browser.inputBox("Please enter your google Cal ID", Browser.Buttons.OK_CANCEL);
  var startdate = Browser.inputBox("Start date using 1/1/2013 format", Browser.Buttons.OK_CANCEL);
  var cal = CalendarApp.getCalendarById(calID);
  var events_sheet = SpreadsheetApp.getActiveSheet();
  var events = cal.getEvents(new Date(startdate), new Date("1/1/2014"));
  var lr = events_sheet.getLastRow();
  var eventarray = new Array();

  var i = 0; // edited
  for (i = 0; i < events.length; i++) {
    line = new Array();
    line.push(events[i].getStartTime());
    line.push(events[i].getTitle());

     //Potential more data that I am not getting at this time
     // line.push(events[i].getDescription());
     // line.push(events[i].getEndTime());

    eventarray.push(line);
  }

  // Append the retreived events to existing spreadsheet
  events_sheet.getRange("A"+(lr+1)+":B"+(lr+i)).setValues(eventarray);

  //remove duplicate rows
  var sheet = SpreadsheetApp.getActiveSheet();
  var data = sheet.getDataRange().getValues();
  var newData = new Array();
  for(i in data){
    var row = data[i];
    var duplicate = false;
    for(j in newData){

      if(row.slice(0,2).join() == newData[j].slice(0,2).join()){
        duplicate = true;
      }
    }
    if(!duplicate){
      newData.push(row);
    }
  }

  // sortFunction used to compare rows of data in our newData array
  function sortFunction( a, b ) {
    // coerce dates to numbers and return comparison
    return ((+a[0]) - (+b[0]))
  }

  // sort ascending by date - retain header lines
  var headers = newData.slice(0,2);
  var sorted = newData.slice(2).sort(sortFunction);
  var newData = headers.concat(sorted);

  // Clear the existing info and update with newData.
  sheet.clearContents();
  sheet.getRange(1, 1, newData.length, newData[0].length).setValues(newData);
}
于 2013-03-20T16:12:19.750 に答える
0

ソートプロセスを含め、ずっと配列レベルにとどまることをお勧めします。

以下のような並べ替え関数を使用して、並べ替えるセルを簡単に選択できます。

// This example sorts on first column of data array
  data.sort(function(x,y){
  var xp = x[0];
  var yp = y[0];
  //Logger.log(xp+'   '+yp);// just to check that it takes the right column
  return xp == yp ? 0 : xp < yp ? -1 : 1;// first sort  ascending
});

重複の削除に関しては、それを行うためのいくつかの方法があります、1つの可能なものはそのようなものです:

var newData = new Array();
  for(var i in data){
    var duplicate = false;
    for(var j in newData){

      if(data[i][0].toString()+data[i].toString() == newData[j][0].toString()+newData[j][1].toString()){ duplicate = true }
    }
    if(!duplicate){ newData.push(data[i]) }
  }
于 2013-03-20T16:13:30.190 に答える