🚀 Optimiser la navigation dans vos bases Google Sheets : Chargement rapide du client précédent avec Apps Script

 

🚀 Optimiser la navigation dans vos bases Google Sheets : Chargement rapide du client précédent avec Apps Script

🧩 Contexte : une fiche dynamique liée à une base de données

Dans un Google Sheet structuré, vous avez une base de données (à partir de la ligne 11) et une fiche de consultation en haut de la feuille. Chaque ligne représente un client, et vous souhaitez permettre à l’utilisateur de naviguer client par client, en affichant ses informations dans une interface structurée (zones G2:G8, J2:J8, etc.).

Initialement, une fonction Consulter_Client_précédent() parcourait les lignes en utilisant getRange(...).getValue() ligne par ligne et cellule par cellule. Ce processus devient extrêmement lent dès que la base contient plusieurs centaines de lignes.


🎯 Objectif : améliorer les performances

Nous allons :

  • Charger toutes les données en mémoire avec getValues() une seule fois ;

  • Éviter les appels répétés à getRange(...).getValue() ;

  • Intégrer la lecture du libellé en S2 et remplir dynamiquement S3 selon ce libellé ;

  • Nettoyer les blocs de consultation sans boucle lente.


✅ Code optimisé : Consulter_Client_précédent()

javascript

function Consulter_Client_précédent() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getActiveSheet(); const dataStartRow = 11; const lastRow = sheet.getLastRow(); const headers = sheet.getRange(10, 1, 1, sheet.getLastColumn()).getValues()[0]; const allData = sheet.getRange(dataStartRow, 1, lastRow - dataStartRow + 1, headers.length).getValues(); let lastUsedRow = Number(sheet.getRange("F1").getValue()); if (!lastUsedRow || lastUsedRow <= dataStartRow) { SpreadsheetApp.getUi().alert("Vous êtes déjà au début de la liste."); return; } for (let i = lastUsedRow - dataStartRow - 1; i >= 0; i--) { const rowValues = allData[i]; const isRowEmpty = rowValues.every(value => value === "" || value === null); const sheetRow = dataStartRow + i; if (!sheet.isRowHiddenByFilter(sheetRow) && !isRowEmpty) { remplirDepuisLigneOptimise(sheet, headers, sheetRow, rowValues); sheet.getRange("F1").setValue(sheetRow); SpreadsheetApp.getUi().alert("Client précédent chargé depuis la ligne " + sheetRow); return; } } SpreadsheetApp.getUi().alert("Aucune autre ligne visible avec données avant la ligne " + lastUsedRow); }

🧠 Fonction associée : remplirDepuisLigneOptimise()

Cette fonction :

  • Nettoie les zones (sans utiliser de boucle lente) ;

  • Parcourt des blocs dynamiques (étiquettes ➜ valeurs) ;

  • Gère également le cas spécial de S2S3.

javascript

function remplirDepuisLigneOptimise(sheet, headers, activeRow, rowValues) { const zones = ["H1", "G2:G8", "J2:J8", "L2:L8", "N2:N8", "P2:P8", "R2:R8", "S3"]; zones.forEach(range => sheet.getRange(range).clearContent()); const colIndexByName = Object.fromEntries(headers.map((h, i) => [h, i])); const blocks = [ { labelCol: "G", valueCol: "H", from: 1, to: 1 }, { labelCol: "F", valueCol: "G", from: 2, to: 8 }, { labelCol: "I", valueCol: "J", from: 2, to: 8 }, { labelCol: "K", valueCol: "L", from: 2, to: 8 }, { labelCol: "M", valueCol: "N", from: 2, to: 8 }, { labelCol: "O", valueCol: "P", from: 2, to: 8 }, { labelCol: "Q", valueCol: "R", from: 2, to: 8 } ]; for (let block of blocks) { for (let i = block.from; i <= block.to; i++) { const label = sheet.getRange(block.labelCol + i).getValue(); const index = colIndexByName[label]; if (index !== undefined) { sheet.getRange(block.valueCol + i).setValue(rowValues[index]); } } } // Cas spécial : libellé dynamique en S2 ➜ valeur en S3 const libelleS2 = sheet.getRange("S2").getValue(); const indexS2 = colIndexByName[libelleS2]; if (indexS2 !== undefined) { sheet.getRange("S3").setValue(rowValues[indexS2]); } // Sauvegarde la ligne active sheet.getRange("F1").setValue(activeRow); }

⚡ Résultat

  • Navigation instantanée même sur plusieurs milliers de lignes ;

  • Moins de requêtes API entre votre script et la feuille (grâce à getValues() global) ;

  • Code plus structuré et réutilisable avec la fonction remplirDepuisLigneOptimise().


📌 Conclusion

Si vous manipulez des bases de données dans Google Sheets avec une interface personnalisée, l’optimisation par chargement en mémoire est indispensable. Non seulement elle rend vos scripts instantanés, mais elle vous ouvre la porte à des interfaces complexes, dynamiques et ultra-réactives.

Commentaires

Posts les plus consultés de ce blog

🛠 Utilisation de CustomUIEditor pour Personnaliser le Ruban Excel

🗓️ Simulateur de Congés et Calendrier Collaboratif sous Google Sheets

Explication VBA : Facturation automatique Gestion client