2017-03-23 15 views
1

GoogleシートのデータをMySQLテーブルにインポートして360秒の実行制限を回避しようとすると、コーディングが行われます。私はバッチ実行を使用していますが、これは大きなデータを持つシートをインポートする手助けとはなりません。 Googleアプリのスクリプトでは、350秒またはいずれかの最初のいずれかのレコードの数を壊して、次の実行を中止した場所からそれを拾う方法がありますか?私はこのケースで何Google Appsスクリプト360秒が制限時間を超えました

var address = 'database_IP_address'; 
var rootPwd = 'root_password'; 
var user = 'user_name'; 
var userPwd = 'user_password'; 
var db = 'database_name'; 

var root = 'root'; 
var instanceUrl = 'jdbc:mysql://' + address; 
var dbUrl = instanceUrl + '/' + db; 

function googleSheetsToMySQL() { 

    var RecId; 
    var Code; 
    var ProductDescription; 
    var Price; 

    var dbconnection = Jdbc.getConnection(dbUrl, root, rootPwd); 
    var statement = dbconnection.createStatement(); 
    var googlesheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('product'); 
    var data = googlesheet.getDataRange().getValues(); 

dbconnection.setAutoCommit(false) 

for (var i = 1; i < data.length; i++) { 
RecId = data[i][0]; 
Code = data[i][1]; 
ProductDescription = data[i][2]; 
Price = data[i][3]; 

var sql = "{call [dbo].[sp_googlesheetstotable](?,?,?,?)}"; 
statement = dbconnection.prepareCall(sql); 
statement.setString(1, RecId); 
statement.setString(2, Code); 
statement.setString(3, ProductDescription); 
statement.setString(4, Price); 
statement.addBatch() 
statement.executeBatch() 
} 

dbconnection.commit() 

答えて

1

は、私はデータベースの起動IDを保存することができます空のシートを作成し、その後、私は10分ごとに実行するスクリプトにトリガを設定します。これを行うには、GASエディタの再生ボタンの左側にある小さな時計アイコンをクリックします。

たとえば、1000レコードのデータベースがあり、トリガーがスクリプトを実行するたびに100レコードを持ち上げたいとします。私はシートを作成します - "Sheet1"と言いましょう - 最初に0をセルA1に入れてください。ガス中の

、私はスクリプトがA1の値にそれが実行されるたびに取得する必要があるだろう:

var ss = SpreadsheetApp.openById("XXXXX"); 
var sheet = ss.getSheetByName("Sheet1"); 
var a1 = sheet.getRange("A1").getValue(); 
var a1 = parseInt(a1); 
var last_row = a1+100; 

その後、あなたのSQL文は次のクエリのようなものでなければなりません:一度

"SELECT * FROM `table` WHERE `id` >= '"+a1+"' AND `id` < '"+last_row+"'" 

クエリが終了してその結果がスプレッドシートに出力されると、は、last_rowで更新します。

sheet.getRange("A1").setValue(last_row); 

スクリプトが再度実行されると(トリガーを介して)、新しい値100が追加され、100200となります)が追加され、100以上200未満の結果が表示され、それに応じて

1

はい、ループされたプロセスによって問題が発生している限り、これは簡単に実行できます。ループがない場合は少しトリッキーで、1つの操作の場合は不可能です。私たちのためにラッキー、あなたのものは最初の種類のようです。本質的には

私たちは、最初にすべてのスクリプトの起動時に知っておく必要があるので、私たちは開始時間を取得するために

var startTime = new Date(); 

を行います。次は

var execTime = new Date(); 
execTime = execTime - startTime 
(個人的に私は最初の変数を宣言するだろうし、ここではVARを持っていないが、それはちょうど私の文体の好みである)あなたの forループの内側に、我々は追加することになりますので、それは各反復の後で何時間チェックする必要があります

これは、スクリプトが実行されている時間を示します。もしあなたが想像したいのであれば、あなたのループが平均的にどれくらいの時間を費やしているかをチェックし、十分な時間が残っているかどうかを調べることができます。それから、いくつかのことをする必要があります。まず第一に、あなたはkeyは、プロパティの名前、valueはあなたが保存したいオブジェクトである

PropertiesService.getScriptProperties().setProperty(key, value) 

を使用することによって、あなたが持っているデータを保存したいです。配列の場合は、文字列をJSONにしてください。また、中止した場所から発射するトリガを作成する必要があります。詳しくはhereをご覧ください。もちろん、最初にトリガを作成してプロパティを保存することはできますが、問題はありません。ここで

は私のスクリプトでこのセグメントを行いfuncionの例です。

function autoTrigger(passProperties, sysKeys) { 
    var sysProperties = new systemProperties(); 

    if (typeof sysKeys === 'undefined' || sysKeys === null) { 
    sysKeys = new systemKeys(); 
    } 

    var triggerID = ScriptApp.newTrigger('stateRebuild') 
          .timeBased() 
          .after(60000) 
          .create() 
          .getUniqueId(); 

    Logger.log('~~~ RESTART TRIGGER CREATED ~~~'); 

//------------------------------------------------------------------------------------------------- 
// In order to properly retrieve the time later, it is stored in milliseconds 
    passProperties.timeframe.start = passProperties.timeframe.start.getTime(); 
    passProperties.timeframe.end = passProperties.timeframe.end.getTime(); 
//------------------------------------------------------------------------------------------------- 

//------------------------------------------------------------------------------------------------- 
// Properties are stored in User Properties using JSON 
    PropertiesService.getUserProperties() 
        .setProperty(sysKeys.startup.rebuildCache, JSON.stringify(passProperties)); 
//------------------------------------------------------------------------------------------------- 

    Logger.log('~~~ CURRENT PROPERTIES STORED ~~~'); 
    return triggerID; 
} 

は、今すぐあなたのスクリプトを停止する必要があります。これはthrowで行います。ここで私はそれをやった方法です:

if (typeof execProperties.nextPageId !== 'undefined' && execProperties.nextPageId) { 
    if (isTimeUp(startTime, Math.max(averageExec, execTime)) === true) { 
    autoTrigger(execProperties); 
    throw new Error('Script reseting'); 
    } 
} 

ここで私はちょうど場合のために1分おきます。

function isTimeUp(start, need) { 
    var cutoff = 500000 // in miliseconds (5 minutes) 
    var now = new Date(); 
    return cutoff - (now.getTime() - start.getTime()) < need; 
} 

私のケースでは、別の起動プロシージャと同じスクリプトが呼び出されないことに注意してください。あなたがする必要があるのは、プロパティに保存した値を取得するようにスクリプトを調整することです。プロパティーhereをさらに読むことができます。したがって、スクリプトでプロパティを見つけることができたら、トリガーを削除し、変数を取得してすべてのプロパティをクリアしてから、ループまでスキップします。これは、ifステートメントの2つのステートメントで簡単に行うことができます。

これが役に立ちます。

関連する問題