وظيفة السحابة الإلكترونية لاستيراد بيانات ملفات CSV إلى "جداول بيانات Google" بشكل تلقائي

1. مقدمة

الهدف من هذا الدرس التطبيقي حول الترميز هو أن تفهم كيفية كتابة دالة Cloud للتفاعل مع عملية تحميل ملف CSV إلى Cloud Storage، وقراءة محتواه واستخدامه لتعديل جدول بيانات Google باستخدام Sheets API.

e9c78061022a6760.png

ويمكن اعتبار ذلك بمثابة عملية تشغيل آلي لخطوة "الاستيراد كملف CSV" التي تتم يدويًا في العادة. سيضمن لك ذلك إمكانية تحليل البيانات (التي قد ينتجها فريق آخر) في جدول بيانات فور توفّرها.

إليك الشكل الذي تبدو عليه عملية التنفيذ :

52df703605ae4bd3.png

2. الإعداد والمتطلبات

إعداد البيئة بالسرعة التي تناسبك

  1. سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. (إذا لم يكن لديك حساب على Gmail أو G Suite، عليك إنشاء حساب).

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

تذكَّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس العملي باسم PROJECT_ID.

  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.

لن تكلفك تجربة هذا الدرس التطبيقي حول الترميز الكثير من المال، إن لم تكلفك شيئًا على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا تتحمّل رسومًا تتجاوز هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.

3- إنشاء "جدول بيانات Google" وضبط إعداداته وتفعيل واجهة برمجة التطبيقات

أولاً، لننشئ مستند "جداول بيانات Google" جديدًا (يمكن أن يكون هذا الجدول ملكًا لأي مستخدم). بعد إنشاء السرّ، تذكَّر المعرّف الخاص به، إذ سيتم استخدامه كمتغيّر بيئة للدالة التي سنكتبها :

dd77d5fc1364ad3e.png

من وحدة تحكّم Google Cloud Platform، فعِّل Google Sheets API في مشروعك الذي تم إنشاؤه حديثًا من خلال الانتقال إلى "واجهات برمجة التطبيقات والخدمات" ثم إلى قسم "مكتبة واجهات برمجة التطبيقات":

c64e2e98b8b55f16.png

في قسم "إدارة الهوية وإمكانية الوصول والمشرف"، انتقِل إلى "حسابات الخدمة" (Service accounts) واحتفِظ بعنوان البريد الإلكتروني لحساب الخدمة التلقائي في App Engine. يجب أن يكون على الشكل your-project-id@appspot.gserviceaccount.com. يمكنك بالطبع إنشاء حساب خدمة مخصّص لهذا الإجراء.

6e279d7e07d4febf.png

أخيرًا، ما عليك سوى منح حساب الخدمة هذا امتيازات التعديل في جدول البيانات باستخدام الزر "مشاركة":

c334062465ddf928.png

من خلال عملية الإعداد هذه، يمكننا الآن كتابة Cloud Function وإعدادها لاستخدام حساب الخدمة هذا. سيتمكّن من الكتابة في مستند جدول البيانات الذي أنشأناه للتو.

4. إنشاء حزمة تخزين

لننشئ الحزمة التي ستراقبها وظيفة السحابة الإلكترونية بحثًا عن ملفات CSV جديدة.

في وحدة التحكّم، استخدِم القائمة على يمين الصفحة للانتقال إلى "مساحة التخزين"... :

2ddcb54423979d25.png

... وإنشاء مجموعة جديدة باسم csv2sheet-POSTFIX (استبدِل POSTFIX باسم فريد) مع ضبط جميع الإعدادات الأخرى على قيمها التلقائية :

dd637080ade62e81.png

5- إنشاء دالة Cloud

يمكننا الآن إنشاء Cloud Function باسم csv2sheet يتم تشغيلها عند تحميل الملفات إلى حزمة Cloud Storage معيّنة. سيتم كتابة الرمز في Node.js 8 باستخدام الدوال غير المتزامنة باستخدام المحرّر المضمّن مباشرةً في Cloud Console :

6ee1a5ce63174ae8.png

احرِص على ضبط "المشغّل" على Cloud Storage وتعديل اسم الحزمة إلى الاسم الذي أنشأته في الخطوة السابقة.

عدِّل أيضًا نقطة الدخول للدالة التي سنكتبها إلى csv2sheet :

446e7c7c992c2d8a.png

الآن، غيِّر نص الدالة إلى :

  1. استخدام واجهات برمجة التطبيقات Cloud Storage وSheets
  2. وضع علامة async على الدالة csv2sheet
  3. احصل على fileName من البيانات الوصفية لحدث Cloud Storage واستخرِج اسمًا لورقة البيانات الجديدة التي سننشئها :
const {google} = require("googleapis");
const {Storage} = require("@google-cloud/storage")

exports.csv2sheet = async (data, context) => {
  var fileName = data.name;
  // basic check that this is a *.csv file, etc...
  if (!fileName.endsWith(".csv")) {
    console.log("Not a .csv file, ignoring.");
    return;
  }
  // define name of new sheet  
  const sheetName = fileName.slice(0, -4);

  // TODO!
};

يجب استخدام async هنا لاستخدام await كما سنرى بعد قليل.

يتضمّن إنشاء هذه الدالة بعض الخيارات المهمة (انقر على الرابط "المزيد" في أسفل الشاشة) :

  • استخدِم القائمة المنسدلة لاختيار حساب الخدمة الموضّح أعلاه.
  • حدِّد متغيّر بيئة باسم SPREADSHEET_ID يجب أن يتطابق مع مستند ورقة البيانات الذي أنشأته سابقًا :

fd22d1873bcb8c66.png

كخطوة أخيرة في عملية الإعداد، إليك محتوى package.json مع Cloud Storage وGoogle Sheets API كعنصرَين من العناصر التابعة التي سنستخدمها (استخدِم علامة التبويب PACKAGE.JSON في المحرّر المضمّن بوحدة التحكّم) :

{
    "name": "csv2sheet",
    "version": "0.0.42",
    "dependencies": {
        "googleapis": "^51.0.0",
        "@google-cloud/storage": "^5.0.1"
    }
}

بعد ضبط جميع الإعدادات على النحو الموضّح، انقر على "إنشاء". بعد دقيقة قصيرة، من المفترض أن يتم إنشاء الدالة ونشرها.

6. إعداد المصادقة وSheets API

قبل كتابة أي رمز إضافي في دالة Cloud باستخدام المحرّر المضمّن، علينا حظر إنشاء Google Client API باستخدام نطاقات Storage وSheet المناسبة (تذكَّر أنّ هذا جزء من دالة async).

في أداة تعديل الدوال في وحدة التحكّم، انقر على "تعديل" (EDIT) وأضِف الرمز التالي إلى نص الدالة csv2sheet :

// block on auth + getting the sheets API object
const auth = await google.auth.getClient({
  scopes: [
    "https://www.googleapis.com/auth/spreadsheets",
    "https://www.googleapis.com/auth/devstorage.read_only"
  ]
});

من هنا، يمكننا إنشاء عميل لواجهة برمجة التطبيقات Sheets API :

const sheetsAPI = google.sheets({version: 'v4', auth});

7. استخدام واجهة برمجة التطبيقات Sheets API لإنشاء ورقة فارغة

باستخدام عميل Sheets API، يمكننا إنشاء ورقة بيانات جديدة بسيطة في مستندنا، ولكن قبل المتابعة، إليك ملاحظة سريعة حول المفردات:

  • جدول البيانات هو المستند الفعلي ويتم الرجوع إليه من خلال المعرّف الخاص به (الموضّح أعلاه والذي يظهر في عنوان URL للمستند)
  • ورقة البيانات هي إحدى علامات التبويب في المستند ويمكن الرجوع إليها من خلال اسمها (اسم علامة التبويب) أو معرّف يتم إنشاؤه عند إنشاء ورقة البيانات

مع أخذ ذلك في الاعتبار، إليك دالة تستخدم برنامج Sheets API لإنشاء ورقة بيانات فارغة في الموضع 2 (عادةً بعد "Sheet1" التلقائية)، مع 26 عمودًا و2000 صف، وتجميد الصف الأول (أضِفها إلى الدالة باستخدام المحرّر المضمّن) :

function addEmptySheet(sheetsAPI, sheetName) {
  return new Promise((resolve, reject) => {
    const emptySheetParams = {
      spreadsheetId: process.env.SPREADSHEET_ID,
      resource: {
        requests: [
          {
            addSheet: {
              properties: {
                title: sheetName,
                index: 1,
                gridProperties: {
                  rowCount: 2000,
                  columnCount: 26,
                  frozenRowCount: 1
                }
              }
            }
          }
        ]
      }
    };
    sheetsAPI.spreadsheets.batchUpdate( emptySheetParams, function(err, response) {
        if (err) {
          reject("The Sheets API returned an error: " + err);
        } else {
          const sheetId = response.data.replies[0].addSheet.properties.sheetId;
          console.log("Created empty sheet: " + sheetId);
          resolve(sheetId);
        }
      }
    );
  });
}

لاحظ كيف أنّنا نعتمد على متغير البيئة SPREADSHEET_ID الذي تم إنشاؤه سابقًا بدلاً من الترميز الثابت للمرجع إلى جدول البيانات.

علينا تذكُّر sheetId للطلبات الإضافية المقدَّمة إلى ورقة البيانات هذه. يجب أيضًا أن يكون اسم ورقة البيانات فريدًا، وسيتعذّر إنشاء ورقة البيانات إذا كانت هناك ورقة بيانات أخرى تحمل الاسم sheetName.

الدالة batchUpdate في واجهة برمجة التطبيقات Sheets API هي طريقة شائعة للتفاعل مع المستندات، ويمكنك الاطّلاع على وصفها هنا.

8. قراءة البيانات من ملف CSV مخزَّن

بعد أن أصبح لدينا مكان لتخزين بياناتنا، لنطوّر وظيفة السحابة الإلكترونية في المحرّر المضمّن ونستخدم Cloud Storage API للحصول على البيانات الفعلية من الملف الذي تم تحميله وتخزينها في سلسلة:

function readCSVContent(sheetsAPI, file, sheetName) {
  return new Promise((resolve, reject) => {
    const storage = new Storage();
    let fileContents = new Buffer('');
    storage.bucket(file.bucket).file(file.name).createReadStream()
    .on('error', function(err) {
      reject('The Storage API returned an error: ' + err);
    })
    .on('data', function(chunk) {
      fileContents = Buffer.concat([fileContents, chunk]);
    })  
    .on('end', function() {
      let content = fileContents.toString('utf8');
      console.log("CSV content read as string : " + content );
      resolve(content);
    });
  });
}

9- ملء ورقة البيانات التي تم إنشاؤها حديثًا

حان الوقت الآن لتعبئة ورقة البيانات التي أنشأناها باستخدام واجهة برمجة التطبيقات نفسها لعميل "جداول بيانات Google" والبيانات التي جمعناها للتو. سنستفيد من هذه الفرصة أيضًا لإضافة بعض الأنماط إلى أعمدة ورقة البيانات (تغيير حجم خط الصف العلوي وتنسيقه بخط غامق) :

function populateAndStyle(sheetsAPI, theData, sheetId) {
  return new Promise((resolve, reject) => {
    // Using 'batchUpdate' allows for multiple 'requests' to be sent in a single batch.
    // Populate the sheet referenced by its ID with the data received (a CSV string)
    // Style: set first row font size to 11 and to Bold. Exercise left for the reader: resize columns
    const dataAndStyle = {
      spreadsheetId: process.env.SPREADSHEET_ID,
      resource: {
        requests: [
          {
            pasteData: {
              coordinate: {
                sheetId: sheetId,
                rowIndex: 0,
                columnIndex: 0
              },
              data: theData,
              delimiter: ","
            }
          },
          {
            repeatCell: {
              range: {
                sheetId: sheetId,
                startRowIndex: 0,
                endRowIndex: 1
              },
              cell: {
                userEnteredFormat: {
                  textFormat: {
                    fontSize: 11,
                    bold: true
                  }
                }
              },
              fields: "userEnteredFormat(textFormat)"
            }
          }       
        ]
      }
    };
        
    sheetsAPI.spreadsheets.batchUpdate(dataAndStyle, function(err, response) {
      if (err) {
        reject("The Sheets API returned an error: " + err);
      } else {
        console.log(sheetId + " sheet populated with " + theData.length + " rows and column style set.");
        resolve();
      }
    });    
  });
}

يجب إضافة هذا الرمز إلى وظيفة Cloud التي اكتملت الآن بنسبة% 99.

لاحظ كيف يتم دمج البيانات والتصميم كعناصر requests متعددة في طلب واحد من Sheets API batchUpdate. يؤدي ذلك إلى إجراء تعديل أكثر كفاءة ودقة.

يُرجى أيضًا ملاحظة أنّنا نحدّد نطاق تعديل يتطابق مع حجم ورقة البيانات التي أنشأناها. وهذا يعني أنّ المحتوى الذي يتجاوز 26 عمودًا (القيمة columnCount المستخدَمة عند إنشاء ورقة البيانات) سيتعذّر تحميله باستخدام هذا الرمز تحديدًا.

إذا سارت الأمور على ما يرام، يمكنك في هذه المرحلة إجراء ما يلي:

  1. حفظ الدالة المعدَّلة
  2. إفلات ملف CSV في الحزمة
  3. ستظهر البيانات المطابقة في جدول البيانات.

10. وضع كل شيء معًا واختبار المسار

يمكن إجراء طلبات الدوال التي ناقشناها للتو كطلبات حظر متتالية في الدالة الأصلية csv2sheet:

  const sheetId = await addEmptySheet(sheetsAPI, sheetName);
  const theData = await readCSVContent(sheetsAPI, data, sheetName);
  await populateAndStyle(sheetsAPI, theData, sheetId);

إذا كنت بحاجة إلى رمز المصدر الكامل للدالة، يمكنك الحصول عليه هنا (من الأسهل على الأرجح الحصول عليه بالكامل في مجموعة واحدة).

بعد إعداد كل شيء، ما عليك سوى تحميل ملف CSV إلى الحزمة الصحيحة، وستتم إضافة ورقة بيانات جديدة إلى جدول البيانات تتضمّن محتوى الملف. في ما يلي نموذج ملف CSV إذا لم يكن لديك ملف جاهز.

1efae021942e64fa.png

جرِّب تحميل عدّة ملفات إلى الحزمة لمعرفة النتيجة.

11. هذا كل شيء! حان وقت إيقاف البنية الأساسية

أمزح معك، لا توجد بنية تحتية يجب إزالتها، فقد تم تنفيذ كل ذلك بدون خادم.

يمكنك، إذا أردت، حذف وظيفة السحابة الإلكترونية والحزمة التي أنشأتها، أو حتى المشروع بأكمله.

12. ما هي الخطوات التالية؟

بهذا نكون قد انتهينا من هذا الدرس التطبيقي حول الترميز الذي يرشدك إلى خطوات الاستماع إلى عمليات التحميل إلى حزمة Cloud Storage في Cloud Function لتعديل "جدول بيانات Google" باستخدام واجهة برمجة التطبيقات المناسبة.

في ما يلي بعض الخطوات التي يمكنك اتّخاذها :

إذا واجهت مشاكل في هذا الدرس العملي، يمكنك الإبلاغ عن أي مشكلة باستخدام الرابط في أسفل يسار الصفحة.

ونحن نقدِّر ملاحظاتك.