Google Script - Lister et modifier formules liées à d'autres spreadsheets

Google Script - Lister et modifier formules liées à d'autres spreadsheets

Bonjour,

J'ai essayé de chercher si ce thème avait déjà des solutions mais je n'ai pas réussi à trouver.

D'où mon problème:

Je travaille avec des spreadsheets complexe est lourd. Du coup ces spreadsheets sont connectés entre eux via des fonctions importrange.

En même temps, j'ai besoin de faire évoluer ces fichiers tout en gardant la version antérieure pour lui faire faire des itérations.

Du coup, je me retrouve avec une version 1 de mes spreadsheets (version 1 de toutes les spreadsheets) connectées entre eux via des formules importrange et je duplique toutes ces spreadsheets (création version 2 de toutes les spreadsheets) pour refaire les liens entre elles via de nouvelles formules importrange (fonctionnalité existant sur excel mais pas sur sheet pour changer les liens entre feuilles).

Ces manipulations de création de version 2, puis 3 ,..., sont lourdes et sources d'erreurs.

Nota: Egalement ce script pourrait servir, lorsque l'on transforme un excel en Google Sheet !

Ma question:

Savez vous s'il est possible de développer un script pour faire cette fonctionnalité manquante dans Google sheet?

C-a-d:

1- le script scanne toutes les formules du spreadsheet

2- Le script liste tous les IDs et le nom des autres spreadsheet avec lequel il est lié

3- L'utilisateur, indique le nouvel Id par lequel, il souhaite le remplacer

4- L'utilisateur lance un nouveau script pour que celui -ci remplace l'ancien Id par le nouveau dans tout le spreadsheet.

5- Egalement, ce script pourrait effectuer ce scan dans le cadre des nouveau fichier Google sheet créé via un fichier excel ...

Merci pour votre aide et conseil par rapport à cette problématique.

Cordialement

Bonjour,

1- le script scanne toutes les formules du spreadsheet

2- Le script liste tous les IDs et le nom des autres spreadsheet avec lequel il est lié

3- L'utilisateur, indique le nouvel Id par lequel, il souhaite le remplacer

4- L'utilisateur lance un nouveau script pour que celui -ci remplace l'ancien Id par le nouveau dans tout le spreadsheet.

5- Egalement, ce script pourrait effectuer ce scan dans le cadre des nouveau fichier Google sheet créé via un fichier excel ...

Merci pour votre aide et conseil par rapport à cette problématique.

Cordialement

houlà, c'est sûr que travailler avec un sac de nœuds c'est pas facile ... je compatis !

j'espère qu'il y a quand même une hiérarchie de fichiers (maitre > esclave) et qu'il n'y a pas d'imports croisés ...

pour commencer, voici une façon de repérer toutes les formules avec importrange

image

on doit pouvoir ensuite en tirer l'ID si besoin avec une expression régulière (sachant que dans une même formule il peut y avoir plusieurs importrange ...)

mais ce n'est pas nécessaire si on a une table IDavant et IDaprès => dans ce cas il faut aussi modifier le script pour connaître la cellule où se trouve cette formule

les seules questions que je me pose c'est comment déclarer les feuilles liées (demande de google quand on écrit une importrange il me semble)

je n'ai pas compris le point 5 sur excel !


edit : avec N° de ligne et de colonne concernées

script complété plus loin ...

Il y a plus simple ...

en mettant les conditions avant et après, ceci changera directement les données dans les formules

// enable Sheets API at Advanced Google services
function remplacement() {
  const replaceConditions = {
    'ABC': "abc",
    'DEF': "def",
  };
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const requests = Object.entries(replaceConditions).map(([k, v]) => ({
    findReplace: {
      find: k.toString(),
      replacement: v.toString(),
      includeFormulas: true,
      allSheets: true,
    },
  }));
  Sheets.Spreadsheets.batchUpdate({ requests: requests }, ss.getId());
}

les seules questions que je me pose c'est comment déclarer les feuilles liées (demande de google quand on écrit une importrange il me semble)

en effet, il faudra ensuite associer les feuilles

image

Bonjour Mike

encore merci pour ta réactivité. Désolé de ne pas l'être autant que toi....

je suis en déplacement sans accès à mon ordinateur...du coup je regarderais ça à mon retour.

Mais, voici des réponses à tes questions:

Je n'ai pas compris le point 5 sur excel !

en fait lorsque l'on transforme un Excel qui est construit sur la même base que décrit sur mon post d'origine, et qu'on le transforme en sheet, forcément ces liens entre fichier n'existent plus. Sheet transforme le nom du fichier dans la formule par [ n+1], cad [ 1] puis [ 2] et ainsi de suite.

Du coup, je me disais que ce script pourrait lister toutes les cases où existent une formule contenant [ n+1].

Le script ferait ensuite pareil....

en effet, il faudra ensuite associer les feuilles

dans mon cas de figure, les feuilles disposent du même nom entre deux versions de fichier. Du coup, si le scripte arrive à lister toutes ces références à des spredsheets extérieures et qu'il les remplacent par d'autres pré sélectionnés par l'utilisateur, alors ça fonctionnera.

j'ai essayé hier matin, de réutiliser ton premier script, mais je ne suis pas arrivé à remplacer la fonction

Logger.log(f.getName() + ' ligne=' + numRow + ' colonne=' + numCol + ' ' + formule)

j'ai essayé par appendrow, mais par manque de temps je n'y suis pas arrivé à logger les infos, sur une sheet. L'apprentissage en script est long et laborieux !

je réessaie mardi ou mercredi.

désolé et encore merci

Bonjour,

Je n'ai pas compris le point 5 sur excel !

en fait lorsque l'on transforme un Excel qui est construit sur la même base que décrit sur mon post d'origine, et qu'on le transforme en sheet, forcément ces liens entre fichier n'existent plus. Sheet transforme le nom du fichier dans la formule par [ n+1], cad [ 1] puis [ 2] et ainsi de suite.

Du coup, je me disais que ce script pourrait lister toutes les cases où existent une formule contenant [ n+1].

intéressant ... pourrais-tu mettre en ligne un extrait d'un tel fichier ?

j'ai essayé hier matin, de réutiliser ton premier script, mais je ne suis pas arrivé à remplacer la fonction

Logger.log(f.getName() + ' ligne=' + numRow + ' colonne=' + numCol + ' ' + formule)

j'ai essayé par appendrow, mais par manque de temps je n'y suis pas arrivé à logger les infos, sur une sheet. L'apprentissage en script est long et laborieux !

  • dans ce cas, il faut ajouter y mettre la nouvelle formule, c'est à dire en remplaçant l'ID
f.getRange(numRow,numCol).setFormula("ici la nouvelle formule")

ce qui donne ...

function remplacementImportFunctions(){
  var doc = SpreadsheetApp.getActiveSpreadsheet()
  doc.getSheets().forEach(function(f){
    var formules = f.getDataRange().getFormulas()
    var numRow = 0
    formules.forEach(function(row){
      numRow++
      var numCol = 0
      row.forEach(function(formule){
        numCol++
        if (formule!=''){
          if (formule.toLowerCase().indexOf('importrange') > 0) {
            f.getRange(numRow,numCol).setFormula(remplacement(formule))
          }
        }
      })
    })
  })
}
function remplacement(formule){
  var ids = ['idAvant1👉idApres1','idAvant2👉idApres2']
  var nouvelleFormule = formule
  for (var i in ids){
    var regExp = new RegExp(ids[i].split('👉')[0], "g");
    var nouvelleFormule = nouvelleFormule.replaceAll(regExp, ids[i].split('👉')[1])
  }
  return (nouvelleFormule)
}
  • en fait, il est plus intéressant d'utiliser le second script
  • quoique cela dépendra de ce qu'on trouvera dans le fichier d'origine excel

prends ton temps, je suis à ta disposition ...

Bonjour Mike,

j'ai essayé de trouver quelques minutes pour te répondre.

Voici le résultat d'un fichier excel transformé par Google (via la fonction drag & Drop dans drive) pour obtenir un Google Sheet.

J'ai très, très simplifié le fichier dont voici un extrait de résultat:

https://docs.google.com/spreadsheets/d/1uIy6XPhHSAN2VfQO7Qmwkoc8_gvmjtMoLPRMF-X7PNM/edit?usp=sharing

voici le type de formules qui apparaissent :

=VLOOKUP($C141,[16]PI!$B:$BR,36,FALSE)

=VLOOKUP(B3;'[17]FI-Synthesis'!$B:$FF;7;FALSE)

=SUM('[15]Centralisat'!$K:$K)

=VLOOKUP($C156,[18]Export!$B:$DG,[18]Export!CD$1,FALSE)

Concernant ta proposition de script, je suis désolé mais je ne suis arrivé à rien faire...!!!!!

Je vais avoir besoins de quelques années pour m'en sortir je crois, avec l'apprentissage de javascript !

1- En fait rien ne s'affiche dans ma feuille pour essayer de loguer tous les résultats de la recherche des importrange de ton premier script

2- Dans ton dernier script, je ne comprends pas, comment puis-je dire au script, les nouvelles formules à utiliser?

A bientôt

houlà, je n'ai jamais vu une telle traduction !!

on va prendre les choses dans l'ordre ...

  • je suppose que [15], [16], [17] et [18] sont normalement des fichiers externes ? si oui, as-tu ces fichiers au format GSheets ? et je suppose que c'est là que tu mets tes importrange ...
  • les 2 formules en erreur proviennent du fait qu'il s'agit d'une notation anglosaxone de la formule alors que ton fichier est en paramètre FR ... il faut alors remplacer les , par des ;
    • la raison est qu'en France la virgule sert de séparateur des nombres décimaux

une fois ces 2 points résolus on pourra se pencher sur le reste

je vais préparer un jeu de 3 fichiers pour te montrer comment les scripts fonctionnent sur des fichiers sans erreur avec importrange

une démo

je vais préparer un jeu de 3 fichiers pour te montrer comment les scripts fonctionnent sur des fichiers sans erreur avec importrange

image
  • actionne l'une ou l'autre des fonctions (les fichiers de base sont identiques, la seule chose qui diffère c'est le tri)
  • regarde ce qui se passe dans la fonction de la cellule jaune

En réponse:

  • je suppose que [15], [16], [17] et [18] sont normalement des fichiers externes ? si oui, as-tu ces fichiers au format GSheets ? et je suppose que c'est là que tu mets tes importrange ...

Oui tous les xslx sont transformés en sheets et je récupérerais les nouveaux IDs via u. scan du drive

D'accord je comprends mieux comment cela fonctionne, mais je n'ai pas réussit à faire fonctionner la seconde version !

Je me suis créé un fichier de travail basé sur ton modèle

https://docs.google.com/spreadsheets/d/1aTZsr9dbX9Nc6DUN-N2YjjOxUT9_MD9Y1MMDQLmzcb0/edit#gid=2483652...

J'ai ajouté un onglet "Dashboard", où j'aimerais que le script logue toutes les formules contenants "importrange" ou "[15], [16], [17] et [18]" en colonne A, B, C.

Une fois, l'étape précédente effectuée, l'utilisateur saisie les liens des nouveaux google sheet en colonne E et mets true, s'il souhaite que le script effectue le changement.

Une fois, terminé, l'utilisateur lance la fin du script, via le menu (pas besoin de onchange function), pour effectuer la modification des liens, sur toutes les formules où la case checkbox est cochée.

Merci et à bientôt

ok, je regarde cela si possible dans la journée

je regarde aussi s'il est possible de transformer les , en ;

question quand même : pourquoi tu utilises à la base excel et qu'ensuite tu passes à GSheets ?

Bonjour Mike,

"question quand même : pourquoi tu utilises à la base excel et qu'ensuite tu passes à GSheets ?"

Parce que c'est une base que j'utilise dans mon entreprise, que l'on utilise depuis quelques années, basée sur excel.

Seulement, nous avons basculé nos outils de microsoft sur Google.

Bonne journée

J'ai ajouté un onglet "Dashboard", où j'aimerais que le script logue toutes les formules contenants "importrange" ou "[15], [16], [17] et [18]" en colonne A, B, C.

evolution ci-dessous

pour la colonne A je m'en suis tenu pour le moment qu'à une seule occurence

petite évolution ...

  1. tenir compte du fait que dans une seule formule il peut y avoir plusieurs importrange, plusieurs [xx]
  2. tenir compte du fait que dans importrange il est tout à fait possible de n'indiquer que l'ID du fichier
function importCurrentIdFormulas() {
  var doc = SpreadsheetApp.getActiveSpreadsheet()
  var db = doc.getSheetByName('Dashboard')
  var regExp = /\[\d+\]/g
  var regExp3 = /"[\s\S\w]+?"/g
  var regExp2 = /'*\[\d+\][\s\S\w]+?,|'*\[\d+\][\s\S\w]+?;/g
  var regExp1 = /\([\s\S\w]+?",|\([\s\S\w]+?";/g
  doc.getSheets().forEach(function (f) {
    if (f.getName() != db.getName()) {
      var formules = f.getRange(1, 1, f.getLastRow(), 3).getFormulas()
      var numRow = 0
      formules.forEach(function (row) {
        numRow++
        var numCol = 0
        row.forEach(function (formule) {
          numCol++
          if (formule != '') {
            if (formule.toLowerCase().indexOf('importrange') > 0) {
              // var result = [formule.split('/')[5], f.getName(), columnToLetter(numCol) + numRow, "'" + formule]
              var result = [formule.match(regExp1).join('\n').match(regExp3).join('\n'), f.getName(), columnToLetter(numCol) + numRow, "'" + formule]
              db.getRange(db.getLastDataRow() + 1, 1, 1, 4).setValues([result])
            }
            if (formule.match(regExp) != null) {
              var result = [formule.match(regExp).join('\n'), f.getName(), columnToLetter(numCol) + numRow, "'" + formule]
              db.getRange(db.getLastDataRow() + 1, 1, 1, 4).setValues([result])
            }
          }
        })
      })
    }
  })
}
function columnToLetter(column) {
  var temp, letter = '';
  while (column > 0) {
    temp = (column - 1) % 26;
    letter = String.fromCharCode(temp + 65) + letter;
    column = (column - temp - 1) / 26;
  }
  return letter;
}
Object.prototype.getLastDataRow = function (col) {
  var lastRow = this.getLastRow();
  if (col == null) { col = 'A' }
  var range = this.getRange(col + lastRow);
  if (range.getValue() !== "") {
    return lastRow;
  } else {
    return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  }
}

Salut Mike,

ça y est je suis de retour...ton script fonctionne mais il liste uniquement deux formules dans l'ensemble du fichier alors que dans cet exemple il en contient 4:

https://docs.google.com/spreadsheets/d/1aTZsr9dbX9Nc6DUN-N2YjjOxUT9_MD9Y1MMDQLmzcb0/edit#gid=2483652...

J'ai essayé sur mon fichier pro plus complexe et cela est pareil

Bonjour,

tu m'avais précisé ...

en colonne A, B, C.

dans ce cas

var formules = f.getRange(1, 1, f.getLastRow(), f.getLastColumn()).getFormulas()

et j'en trouve 5

parfait Super Mike ca fonctionne bien et cela me liste toutes les formules.

Est il possible maintenant que tu m'aides à développer le script pour remplacer celles ci-par celles qui sont écrites en "colonne F" de l'onglet du "Dashboard", uniquement si la chechbox est cochée?

Merci envore

ok, pas de soucis, c'est le but

attention à bien prévoir les cas où une même formule fait appel à plusieurs sources

mais néanmoins, ne faut-il pas prévoir de les faire en bloc toutes ensemble avec juste une table de conversion avant/après ?

grosso modo, combien en as-tu par fichier ?

Ben, en fait le script a listé 1000 formules mais je pense qu'il s'est arrêter au bout d'un certains temps. Je crois qu'il y a un temps maxi dans les scripts google.

sur mon fichier de travail, il doit y en avoir entre 2 et 3000 !

ces limites de google ne sont pas un problème car je lancerais le script en plusieurs batch, ou sur les premieres lignes je déroulerais sur les autres !

Oui tu as raison, cela n'a pas de sens de faire cette condition par checkbox. Vaut mieux lancer le script pour l'ensemble des formules

Ben, en fait le script a listé 1000 formules mais je pense qu'il s'est arrêter au bout d'un certains temps. Je crois qu'il y a un temps maxi dans les scripts google.

sur mon fichier de travail, il doit y en avoir entre 2 et 3000 !

hum ... copieux ! et comment tu le faisais à la main ? wahoo

combien par feuille ?

Rechercher des sujets similaires à "google script lister modifier formules liees spreadsheets"