Elektronik tablolarla yapılan bir sürü işiniz var ve bu verileri ilişkisel veya NoSql veritabanına taşımadan Nodejs uygulamanıza nasıl entegre edeceğinizi mi merak ediyorsunuz?

Bu mümkün ve bunu nasıl yapacağınızı bu makalede öğreneceksiniz.

Google Sheet bugün küçük işletmeler için önemli bir araç olmaya devam ediyor. Bir uygulama oluşturup gerçek bir veritabanına geçmeden önce ölçeklendirme ihtiyacı bulana kadar bir Google E-Table  başlayan birkaç girişim biliyorum.

Neden Google Sheet yerine gerçek bir arka uç veritabanının kullanılması gerektiğine ilişkin birçok neden verilmiş olsa da, nedenler, verilerin veya sayfanın yanlışlıkla silinmesi, kayıtlarda statik tanımlayıcıların olmaması vb.

Bununla birlikte, bu makale sayfanın avantajlarını gerçek bir arka uç veritabanına göre kasıtlı olarak tasarlamaz veya tam tersi, bazı projeler sayfadaki verileri okumanızı ve uygulamanıza / veritabanınıza senkronize etmenizi veya yönetimsel kullanım için sayfaya yazmanızı gerektirir.

Çoğu küçük proje, düzenli bir veritabanı gerektirmeyebilir ve Google E-Table ile yönetilebilir.

Bu makalede, Nodejs kullanarak Google E-Table okuma sürecinde size yol göstereceğim.

Ön Şartlar; 
Bu eğitim için Google E-Tablosunu okuyan ve ona yazan bir dinlenme API'si oluşturacağız.
Bu eğiticiye başlamadan önce aşağıdakilere ihtiyacınız olacak:

  • Nodejs and NPM yüklenmesi ve kurulması
  • Tabikide bir web tarayıcı 
  • Kimlik doğrulamayı etkinleştirmek için bir google hesabı

Hazırsak başlayalım; 

Google Sheet API'yi Etkinleştirme

Google Sheet API, geliştiricilerin uygulamalarından programlı bir şekilde Google sayfasını okumasını, yazmasını ve biçimlendirmesini sağlayan Google'ın API'sidir.

Aşama 1-)   credentials.json dosyası edinme

Bu dosyası için öncelikle  bu bağlantıyı ve indirmek için “Google E API etkinleştirme” butonuna tıklayın credentials.jsondosyayı aşağıda gösterildiği gibi projenizin adını girmek için gerekli olacak:
s_9190355683C153BCB18A14D16920F69B43895F255B1A0932B5FF3AAA80959B28_1596526218353_Screenshot + 2020/08/04 + at + 8.29.02 + AM.png

Entegre ettiğiniz uygulama türü olarak web sunucusunu **** seçin ve yönlendirme URI'nizi yapılandırmak için * API Konsolu * seçeneğine tıklayın

Konsolunuzdan kimlik bilgilerini seçin ve OAuth client
Ekran görüntüsü 2020-08-02 at 3.14.15 AM.png

Yönlendirme URI'sini yetkilendirin ve kaydedin. (Bu URI, Google ile kimlik doğrulaması yaptıktan sonra yönlendirileceğiniz yerdir. Bu, mutlak bir yol olmalıdır) ve son olarak, kimlik bilgilerinizi indirin Not: Bu eğitici, indirdiğiniz kimlik bilgilerinizin adını * kimlik bilgileris.json * olarak alacaktır , yeniden adlandırabilirsiniz sizinkini kullanmak istediğiniz adı seçin ve dosyayı makalede kullanıldığı gibi istediğiniz dosya adıyla değiştirdiğinizden emin olun .
Ekran görüntüsü 2020-08-02 at 3.23.14 AM.png

Ekran görüntüsü 2020-08-02 at 4.18.29 AM.png
credentials.json

Adım 2-) Gerekli NodeJS Paketlerini Yükleyin

npm install googleapis@39 express http --save
npm install nodemon --save-dev

API'mizi oluşturma

Klasör yapısı

Klasör yapımız aşağıdaki gibi görünecektir . Dosya, sunucumuzu başlatmak ve çalıştırmak için gereken kodu içerir. Aşağıdaki kodu server.js dosyanıza ekleyin.
Ekran görüntüsü 2020-08-02 at 3.42.11 AM.png

server.js içeriği ; 

 const PORT = process.env.PORT || 3000;
    const http = require('http');
    const app = require('./routes/app')
    const server = http.createServer(app);
    server.listen(PORT)

routes klasörünüzün içinde app.js oluşturun ve aşağıdaki kodu ekleyin; 

const express = require('express');
    const indexRoute = require('../routes/index')
    const app = express();
    app.use((req, res, next) => {
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
      res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
      next();
    });
    app.use('/', indexRoute);
    module.exports = app;

Sunucunuzu nodemon terminalinize yazarak başlatın, bu yazmakla aynıdır node server.js. Aradaki fark, kullanıyorsanız kodunuzda her değişiklik yaptığınızda sunucunuzu her zaman durdurmanız ve yeniden başlatmanız gerekmesidir. Ancak Nodemon ile, dizindeki bir dosya değiştiğinde uygulamanızı otomatik olarak yeniden başlatır. Nodemon başlatmaya bilir server.js benim belirtilen çünkü package.json dosyası "main": "server.js"

Sunucunuz çalışıyor olmalı http://localhost:3000

  • Credentials.json * dosyasını google klasörüne kopyalayın.
    Aşağıda, uygulamamızın sayfa api'sini kullanması için kimliğini doğrulamak ve yetkilendirmek için bir sınıf modülü oluşturan kod bulunmaktadır.
 const fs = require('fs')
    const readline = require('readline')
    const {google} = require('googleapis')
    // If modifying these scopes, delete token.json.
    // SCOPE gives additional rules to the sheet, you can restrict rule to readonly or give full access
    const SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    // The path were your token.json file is saved, depends totally on you.
    const TOKEN_PATH = './google/token.json'
    class Authentication {
      authenticated(){
        return new Promise((success, failed) => {
          // Load client secrets from a local file.
            let credentials = this.getClientSecret()
            let authorized = this.authorize(credentials)
            authorized.then(success, failed)
          })

      }
      getClientSecret(){
        return require('./credentials.json')
      }

      /**
       * Create an OAuth2 client with the given credentials, and then execute the
       * given callback function.
       * @param {Object} credentials The authorization client credentials.
       * @param {function} callback The callback to call with the authorized client.
       */
      authorize(credentials) {
        const {client_secret, client_id, redirect_uris} = credentials.web
        const oAuth2Client = new google.auth.OAuth2(
            client_id, client_secret, redirect_uris[0])

            return new Promise((success, failed) => {
              // Check if we have previously stored a token.
              fs.readFile(TOKEN_PATH, (err, token) => {
                if (err) {
                  this.getNewToken(oAuth2Client)
                  .then((oAuth2ClientNew) => {
                    success(oAuth2ClientNew)
                  }, (err) => {
                    failed(err)
                  })
                } else {
                  oAuth2Client.setCredentials(JSON.parse(token))
                  success(oAuth2Client)
                }    
              })
            })
        }

      /**
       * Get and store new token after prompting for user authorization, and then
       * execute the given callback with the authorized OAuth2 client.
       * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
       * @param {getEventsCallback} callback The callback for the authorized client.
       */
      getNewToken(oAuth2Client, callback) {
        return new Promise((success, failed) => {
          const authUrl = oAuth2Client.generateAuthUrl({
            access_type: 'offline',
            scope: SCOPES,
          })
          console.log('Authorize this app by visiting this url:', authUrl)
          const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
          })
          rl.question('Enter the code from that page here: ', (code) => {
            rl.close()
            oAuth2Client.getToken(code, (err, token) => {
              if (err) {
                failed('Error while trying to retrieve access token', err)
              } 
              oAuth2Client.setCredentials(token)
              // Save the token for later program executions
              fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
                if (err) return console.error(err)
                console.log('Token stored to', TOKEN_PATH)
              })
              success(oAuth2Client)
            })
          })
        })
      }
    }

    module.exports = new Authentication

Google klasörünün içinde index.js dosyası oluşturun ve yukarıdaki kodu yapıştırın (kod tabanını açıklamak için yorumlanmıştır.

Routes oluşturmak

Rotalar klasörümüzün içinde index.jsdosya oluşturun ve aşağıdaki kodu ekleyin. Bu, bu uygulama için tüm yolları içermelidir.

 const express = require('express')
    const router = express.Router()
    const { retrieveUsers } = require('../controllers/retrieveFromSheet')
    const { saveUsers } = require('../controllers/saveToSheet')

    router.get('/v1/users', retrieveUsers)
    router.post('/v1/update/users', saveUsers)

    module.exports = router

Denetleyicileri oluşturmak

Denetleyiciler klasörümüzün içinde * retrieveFromSheet.js * ve saveToSheet.js oluşturun.

Uygulamanın kimliğini doğrulayın

Uygulamamıza Sheet'e erişim izni verelim ve ardından indirelim token.json.

Aşağıdaki kodu şuraya ekle: retrieveFromSheet.js

 const authentication = require('../google/index')
    const { google } = require('googleapis')

    exports.retrieveUsers = (req, res) => {
    authentication.authenticated()
      .then((auth) => {
        res.status(200)
        .json('Working')
      })
      .catch(err => {
        res.status(401)
        .json(`you know wetin happen, ${err}`)
      })
    }

tarayıcınızda * localhost: 3000/v1/ users * 'ı açın, ardından terminalinize geri dönün URL'yi terminalinizde açın. Bağlantıya eleştirel bir şekilde bakın , google geliştirici konsolunuzda yapılandırdığınız bağlantıya eklendiğini göreceksiniz .
Ekran görüntüsü 2020-08-02 at 1.57.37 PM.png

Uygulamaya gerekli tüm erişimi verin ve devam edin redirect_uri, yol eklenmiş bir kodla sizi kendinize yönlendirmelidir . kodu kopyalayıp terminalinize yapıştırın ve enter tuşuna basın. * Token.json'u görmeniz gereken google klasörünü açın,  http: // localhost:3000/v1/users 'a geri gidin ve her şey yolunda giderse aşağıdaki gibi  görmelisiniz.

Ekran görüntüsü 2020-08-03, 8.07.15 AM.png

Ekran görüntüsü 2020-08-03 at 7.19.57 AM.png

Sayfamızdan veri almak için bir fonksiyon ekleyelim

 const getFromSheet =  (auth) => {
      return new Promise((success, failed) => {
        const sheets = google.sheets({version: 'v4', auth})
        sheets.spreadsheets.values.get({
          spreadsheetId: '1_c4TS8WO0VqX336OauvYaVlxRzuEkaZ50hJf6yQxZok',
          range: 'approved!A:D',
        }, (err, res) => {
          if (err){
            return failed(err) 
          }
          const rows = res.data.values
          success(rows)
        })
      })
    }

Geri alma kullanıcılarını arayın : getFromSheet

   getFromSheet(auth).then((response) => {
      res.status(200).
      json(response)
    })
    .catch(err => {
      console.log(`i no gree fetch data from sheet, ${err}`)
    })

Şimdi tarayıcıdan adresimizi yenileyelim  http://localhost: 3000/v1/users  ve alınan kullanıcılarımız bir dizi dizisi olmalıdır.

Ekran görüntüsü 2020-08-03 at 7.47.30 PM.png

Şimdi geri alınan kullanıcılarımızı daha güzel görünecek şekilde biçimlendirelim.

retrieveFromSheet.js dosyamız şöyle olmalıdır. 

const authentication = require('../google/index')
    const { google } = require('googleapis')
    const getFromSheet =  (auth) => {
      return new Promise((success, failed) => {
        const sheets = google.sheets({version: 'v4', auth})
        sheets.spreadsheets.values.get({
          spreadsheetId: '1_c4TS8WO0VqX336OauvYaVlxRzuEkaZ50hJf6yQxZok',
          range: 'approved!A:D',
        }, (err, res) => {
          if (err){
            return failed(err) 
          }
          const rows = res.data.values

          // format retrieved data
          if (rows.length) {
              var rowHead = rows.shift()
              const formatedUsers = rows.map((row) => {
                  return rowHead.reduce( (obj, key, i) => {
                    obj[key] = row[i]
                    return obj
                  }, {})
              })
              success(formatedUsers)   
          } else {
            failed('No data found.')
          }
        })
      })
    }
    exports.retrieveUsers = (req, res) => {
      authentication.authenticated()
      .then((auth) => {
        getFromSheet(auth).then((response) => {
          res.status(200)
          .json({
            message: response
          })
        })
        .catch(err => {
          res.status(404)
          .json({
            error: `i no gree fetch data from sheet, ${err}`
          })
        })
      })
      .catch(err => {
        res.status(401)
        .json({
          error: `you know wetin happen, ${err}`
        })
      })
    }

Kullanıcılar artık aşağıdaki gibi böyle görünmeli;


Ekran görüntüsü 2020-08-04, 7.14.26 AM.png

Şimdi yukarıda yaptıklarımızı daha iyi anlamak için kod tabanını tekrar küçük parçalar halinde gözden geçirelim.

 sheets.spreadsheets.values.get({
          spreadsheetId: '1_c4TS8WO0VqX336OauvYaVlxRzuEkaZ50hJf6yQxZok',
          range: 'approved!A:D',
        }

Buradaki range nedir?

Bir sayfadaki tek bir hücre veya bir sayfadaki bitişik hücreler grubu olabilir. Örneğin yukarıdaki kodumuzda bir aralık belirledik - onaylı! A: D. * onaylandı *, aşağıdaki resimde gösterildiği gibi sayfanın adını gösterir.

Sayfanın tamamına çalışma kitabı denir

Ekran görüntüsü 2020-08-03 at 8.30.21 PM.png

! A: D , A sütunundan D sütununa başlamak anlamına gelir .
! B2: D3 , sütun B satır 2'den D sütun 3'e başlamak anlamına gelir.

values.get , yukarıdaki örnekte gösterildiği gibi tek bir aralıktaki değerleri almak için kullanılır.
values.batchGet , aynı anda birden çok aralıktan almak için kullanılır.

BatchGet'i kullanmak için aralığınızı olarak değiştirin, ranges: ['approved!B2:D3', 'approved!A1:C2']bir dizi farklı aralık alır. batchGet kullanılarak, döndürülen veriler öğesinden yok edilir res.data.valueRanges.

spreadsheetId: '1_c4TS8WO0VqX336OauvYaVlxRzuEkaZ50hJf6yQxZok', spreadsheetId çalışma kitabınızın kimliğini ifade eder
Ekran görüntüsü 2020-08-04 at 6.10.32 AM.png

 

Promises Nedir? 

Basitçe eşzamansız bir işlemin tamamlanması (veya başarısızlığı) anlamına gelir. Bir söz ancak bir kez başarılı olabilir veya başarısız olabilir.

Burada başarılı veya başarısız bir nesneyi iade etme sözü verdik.

   const getFromSheet =  (auth) => {
      return new Promise((success, failed) => {

Sonuç Olarak

Sayfadan yeni aldığımız veriler, ön tarafımıza sunulabilir, uygulamamızda analiz için kullanılabilir veya varsa gerçek bir arka uç veritabanına kaydedilebilir.
Bir sonraki yazımda, Google E-Tablolar'a ve daha fazlasına nasıl kaydedileceğine bir göz atacağız.