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

1. مقدمة

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

e9c78061022a6760.png

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

إليك الشكل الذي يظهر به التنفيذ :

52df703605ae4bd3.png

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

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

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

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZwci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ8-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 في مشروعك الذي تم إنشاؤه حديثًا من خلال الانتقال إلى قسم "واجهات برمجة التطبيقات والخدمات" (APIs and Services) ثم "مكتبة واجهات برمجة التطبيقات" (API Library):

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 Sheet 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 لإنشاء ورقة بيانات فارغة

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

  • جدول البيانات هو المستند الفعلي ويتم الرجوع إليه من خلال المعرّف الخاص به (الموضّح أعلاه والذي يظهر في عنوان 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 في واجهة برمجة التطبيقات الخاصة بـ "جداول بيانات Google" طريقة شائعة للتفاعل مع المستندات، ويمكنك الاطّلاع على وصف لها هنا.

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. ملء ورقة البيانات التي تم إنشاؤها حديثًا

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

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 باستخدام واجهة برمجة التطبيقات المناسبة.

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

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

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