← Alle guides

Det levende dokumentregister — Byg en dokumentoversigt i Google Drive der holder sig selv ajour

Et manuelt dokumentregister dør altid. Her bygger vi et Google Sheet der automatisk scanner jeres Drive-mappestruktur, registrerer alle dokumenter og holder sig selv opdateret — med gratis værktøjer I allerede har.

Det levende dokumentregister — Byg en dokumentoversigt i Google Drive der holder sig selv ajour

Hvis du har fulgt Guide 1 — Fundamentet, har du allerede en mappestruktur, fem kerneregistre og en dokumentstandard. Dokumentoversigten — det centrale register over al dokumenteret information — er rygraden i hele kvalitetsledelsessystemet. Men der er et problem: den er manuelt vedligeholdt. Hver gang du opretter et dokument, ændrer et filnavn eller flytter en fil, skal du ind og opdatere registret. Og det gør du de første tre uger. Derefter glemmer du det.

Denne guide løser det problem. Vi bygger en dokumentoversigt i Google Sheets, der opdaterer sig selv automatisk. Den scanner jeres Google Drive-mappestruktur, finder alle dokumenter, registrerer stier, ejere, senest ændret-dato og genererer klikbare links — og den gør det af sig selv, én gang i døgnet, uden at du rører den.

Det eneste, du skal bruge, er Google Workspace (som du allerede betaler for) og Apps Script (som er gratis og indbygget). Ingen tilkøb, ingen tredjepartsværktøjer, ingen abonnementer.

0 kr.i ekstra software
~30 minfra start til kørende register
1×/dagautomatisk opdatering

Del 1 · Problemet

Hvorfor manuelle dokumentregistre dør

Et manuelt dokumentregister har en indbygget fejl: det kræver, at nogen husker at opdatere det, hver gang noget ændrer sig. Det lyder trivielt. Det er det ikke. I en organisation med 50–200 ISO-dokumenter sker der ændringer ugentligt — nye procedurer, reviderede instrukser, omdøbte filer, flyttede dokumenter. Hvert skridt, der ikke registreres, udvider gabet mellem registret og virkeligheden.

Og gabet er usynligt. Ingen opdager det i hverdagen, fordi ingen bruger registret i hverdagen. Det er først, når auditoren spørger — "Kan I vise mig jeres gældende dokumentoversigt?" — at I opdager, at den gældende version er tre måneder gammel, mangler de seneste ni dokumenter, og har stier, der ikke længere eksisterer.

Manuelt register

Opdateres af én person, når vedkommende husker det. Stier, der ikke længere passer. Dokumenter, der mangler. Versioner, der ikke stemmer. Auditoren spørger, og du bruger tyve minutter på at forklare, hvorfor registret er "lidt bagud".

Selvvedligeholdende register

Kører af sig selv én gang i døgnet. Alle filer registreres automatisk med sti, ejer, dato og klikbart link. Nye filer markeres. Slettede filer flagges. Registret er altid gældende — fordi det aldrig er afhængigt af, at nogen husker at opdatere det.


Del 2 · Resultatet

Hvad vi bygger

Inden vi går i gang med koden, er det vigtigt at forstå, hvad slutproduktet er. Vi bygger et Google Sheet med følgende kolonner:

  • Dokument-ID — automatisk udledt fra filnavnet (fx "30-01" fra "30-01 Procedur for dokumentstyring").
  • Dokumentnavn — filens fulde navn som klikbart link direkte til dokumentet.
  • Type — filtype (Google Docs, Sheets, PDF, etc.).
  • Mappesti — den fulde sti fra jeres ISO-rodmappe (fx "30 Støtte / 30-01 Dokumentstyring").
  • Ejer — filens ejer i Google Drive.
  • Sidst ændret — dato og klokkeslæt for seneste ændring.
  • Status — automatisk vurdering: "Ny" (set første gang), "Ændret" (ændret siden sidst), "OK" (uændret), "Slettet" (fandtes i sidste scan, men ikke længere).
  • Sidst scannet — tidsstempel for det seneste scan, så I altid kan se, hvor aktuelt registret er.

Registret kører automatisk én gang i døgnet via en tidsbaseret trigger. Du kan også køre det manuelt fra en knap direkte i arket.


Del 3 · Opsætning

Trin for trin: Fra tomt ark til kørende register

Hele opsætningen tager ca. 30 minutter. Du behøver ingen programmeringserfaring — al kode er klar til at kopiere ind.

1

Opret et nyt Google Sheet

Giv det et navn som "ISO Dokumentoversigt — Automatisk" og gem det i jeres ISO-rodmappe (eller i en mappe til administrative ISO-værktøjer). Det bliver jeres levende dokumentregister.

2

Opret kolonnerne

Skriv følgende kolonneoverskrifter i række 1: Dokument-ID | Dokumentnavn | Type | Mappesti | Ejer | Sidst ændret | Status | Sidst scannet. Gør række 1 fed og frys den, så overskrifterne altid er synlige.

3

Åbn Apps Script

I dit Google Sheet: klik på Udvidelser → Apps Script. Det åbner en kodeeditor i en ny fane. Slet det tomme indhold i Code.gs — vi erstatter det med vores script.

4

Kopiér scriptet ind

Kopiér hele scriptet fra prompt-blokken herunder, og indsæt det i Code.gs. Erstat de to konfigurationslinjer øverst med jeres eget mappe-ID.

5

Find jeres mappe-ID

Åbn jeres ISO-rodmappe i Google Drive. I URL'en ser du noget som: drive.google.com/drive/folders/1aBcDeFgHiJkLmNoPqRsTuVwXyZ. Det lange ID efter /folders/ er jeres mappe-ID. Kopiér det ind i scriptets CONFIG-objekt.

6

Kør scriptet første gang

Vælg funktionen 'opdaterRegister' i dropdown-menuen øverst og klik på ▶ Kør. Google beder om tilladelse til at læse jeres Drive og skrive i jeres Sheet — godkend det. Første kørsel tager 10–30 sekunder afhængigt af antal filer.

7

Opsæt automatisk kørsel

Kør funktionen 'opretDagligTrigger' én gang. Den opretter en tidsbaseret trigger, der kører scriptet automatisk hver nat. Du behøver aldrig gøre det igen — triggeren kører af sig selv.


Del 4 · Scriptet

Den fulde kode — klar til at kopiere

Herunder er hele scriptet. Det er skrevet i Google Apps Script (som er JavaScript) og gør følgende: scanner jeres ISO-mappe og alle undermapper, bygger den fulde mappesti til hver fil, registrerer metadata, sammenligner med det forrige scan for at markere nye, ændrede og slettede filer, og skriver resultatet til jeres Google Sheet.

Før du kopierer

Du skal ændre én ting: ROOT_FOLDER_ID i CONFIG-objektet øverst i scriptet. Erstat den med ID'et på jeres ISO-rodmappe i Google Drive. Alt andet virker uden ændringer.

Apps Script — Kopiér hele blokken ind i Code.gs/** * ISO Dokumentregister — Automatisk opdatering * Scanner en Google Drive-mappe og alle undermapper, * og opdaterer et Google Sheet med filmetadata. */ const CONFIG = { // ⬇️ ERSTAT MED JERES ISO-RODMAPPES ID ⬇️ ROOT_FOLDER_ID: "INDSÆT_JERES_MAPPE_ID_HER", // Arket i dette Google Sheet der bruges til registret. // Ændr kun hvis I omdøber arket. SHEET_NAME: "Ark1", }; /** * Hovedfunktion — kald denne manuelt eller via trigger. */ function opdaterRegister() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheetByName(CONFIG.SHEET_NAME); if (!sheet) { throw new Error("Arket '" + CONFIG.SHEET_NAME + "' blev ikke fundet."); } // Hent forrige scan (til sammenligning) const forrigeData = hentForrigeData(sheet); // Scan Drive const rootFolder = DriveApp.getFolderById(CONFIG.ROOT_FOLDER_ID); const filer = []; scanMappe(rootFolder, "", filer); // Byg nye rækker med status const tidsstempel = new Date(); const nyeRaekker = filer.map(function(fil) { const forrige = forrigeData[fil.id]; let status = "OK"; if (!forrige) { status = "Ny"; } else if (fil.sidstAendret.getTime() !== forrige.sidstAendret.getTime()) { status = "Ændret"; } return [ fil.dokumentId, fil.navn, fil.type, fil.mappesti, fil.ejer, fil.sidstAendret, status, tidsstempel, fil.url, fil.id, ]; }); // Find slettede filer (fandtes i forrige scan, men ikke i dette) const aktuelleIds = {}; filer.forEach(function(f) { aktuelleIds[f.id] = true; }); Object.keys(forrigeData).forEach(function(id) { if (!aktuelleIds[id]) { var f = forrigeData[id]; nyeRaekker.push([ f.dokumentId, f.navn, f.type, f.mappesti, f.ejer, f.sidstAendret, "Slettet", tidsstempel, "", id, ]); } }); // Sortér efter Dokument-ID nyeRaekker.sort(function(a, b) { return String(a[0]).localeCompare(String(b[0])); }); // Skriv til sheet sheet.getRange(2, 1, sheet.getMaxRows() - 1, 10).clearContent(); if (nyeRaekker.length > 0) { sheet.getRange(2, 1, nyeRaekker.length, 10).setValues(nyeRaekker); } // Gør dokumentnavne til klikbare links for (var i = 0; i < nyeRaekker.length; i++) { var url = nyeRaekker[i][8]; var navn = nyeRaekker[i][1]; if (url) { var richText = SpreadsheetApp.newRichTextValue() .setText(navn) .setLinkUrl(url) .build(); sheet.getRange(i + 2, 2).setRichTextValue(richText); } } // Skjul hjælpekolonner (URL og fil-ID) sheet.hideColumns(9, 2); // Farvelæg status-kolonnen farvelaegStatus(sheet, nyeRaekker.length); Logger.log("Register opdateret: " + nyeRaekker.length + " filer."); } /** * Scanner en mappe og alle undermapper rekursivt. */ function scanMappe(mappe, sti, resultat) { var mappenavn = mappe.getName(); var nuSti = sti ? sti + " / " + mappenavn : mappenavn; // Scan filer i denne mappe var filer = mappe.getFiles(); while (filer.hasNext()) { var fil = filer.next(); var navn = fil.getName(); // Udled Dokument-ID fra filnavn (fx "30-01" fra "30-01 Procedur...") var idMatch = navn.match(/^(\d{2}-\d{2})/); var dokumentId = idMatch ? idMatch[1] : "—"; resultat.push({ id: fil.getId(), dokumentId: dokumentId, navn: navn, type: oversaetType(fil.getMimeType()), mappesti: nuSti, ejer: fil.getOwner() ? fil.getOwner().getEmail() : "Ukendt", sidstAendret: fil.getLastUpdated(), url: fil.getUrl(), }); } // Scan undermapper var undermapper = mappe.getFolders(); while (undermapper.hasNext()) { scanMappe(undermapper.next(), nuSti, resultat); } } /** * Henter data fra forrige scan til sammenligning. * Returnerer et objekt med fil-ID som nøgle. */ function hentForrigeData(sheet) { var data = {}; var lastRow = sheet.getLastRow(); if (lastRow < 2) return data; var vaerdier = sheet.getRange(2, 1, lastRow - 1, 10).getValues(); vaerdier.forEach(function(row) { var id = row[9]; // Fil-ID i kolonne 10 if (id) { data[id] = { dokumentId: row[0], navn: row[1], type: row[2], mappesti: row[3], ejer: row[4], sidstAendret: new Date(row[5]), }; } }); return data; } /** * Oversætter MIME-type til et læsbart format. */ function oversaetType(mimeType) { var typer = { "application/vnd.google-apps.document": "Google Docs", "application/vnd.google-apps.spreadsheet": "Google Sheets", "application/vnd.google-apps.presentation": "Google Slides", "application/vnd.google-apps.form": "Google Formular", "application/pdf": "PDF", "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "Word", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "Excel", "application/vnd.openxmlformats-officedocument.presentationml.presentation": "PowerPoint", "image/png": "Billede (PNG)", "image/jpeg": "Billede (JPG)", }; return typer[mimeType] || mimeType; } /** * Farvelægger status-kolonnen for nem aflæsning. */ function farvelaegStatus(sheet, antalRaekker) { if (antalRaekker === 0) return; var range = sheet.getRange(2, 7, antalRaekker, 1); var vaerdier = range.getValues(); for (var i = 0; i < vaerdier.length; i++) { var celle = sheet.getRange(i + 2, 7); switch (vaerdier[i][0]) { case "Ny": celle.setBackground("#d9ead3"); // Grøn break; case "Ændret": celle.setBackground("#fff2cc"); // Gul break; case "Slettet": celle.setBackground("#f4cccc"); // Rød break; default: celle.setBackground(null); // Ingen farve } } } /** * Opretter en daglig trigger — kør denne funktion én gang. */ function opretDagligTrigger() { // Slet eksisterende triggers først var triggers = ScriptApp.getProjectTriggers(); triggers.forEach(function(t) { if (t.getHandlerFunction() === "opdaterRegister") { ScriptApp.deleteTrigger(t); } }); // Opret ny daglig trigger kl. 06:00 ScriptApp.newTrigger("opdaterRegister") .timeBased() .everyDays(1) .atHour(6) .create(); Logger.log("Daglig trigger oprettet — kører hver dag kl. 06:00."); }

Del 5 · Sådan virker det

Under motorhjelmen

Scriptet gør fire ting, og det er vigtigt at forstå dem, fordi de tilsammen løser de problemer, et manuelt register aldrig kan:

1. Rekursiv scanning

Scriptet starter i jeres ISO-rodmappe og arbejder sig ned igennem hele mappestrukturen — mappe for mappe, fil for fil. For hver fil registrerer det: navn, MIME-type (som oversættes til "Google Docs", "PDF" osv.), ejer, sidst ændret og et direkte link. Det bygger den fulde mappesti undervejs, så I altid kan se præcis hvor en fil ligger i hierarkiet.

2. Automatisk ID-genkendelse

Hvis I følger konventionen fra Guide 1 og navngiver filer med ID først (fx "30-01 Procedur for dokumentstyring"), udleder scriptet automatisk Dokument-ID'et fra filnavnet. Det gør, at registret sorterer korrekt og matcher jeres nummersystem uden manuelt arbejde.

3. Snapshot-sammenligning

Ved hvert scan sammenligner scriptet det aktuelle resultat med det forrige. Det gemmer fil-ID'er, så det kan genkende den samme fil, selv hvis den er blevet omdøbt eller flyttet. Resultatet er en status på hver fil:

  • Ny — filen er set for første gang (oprettet siden sidste scan).
  • Ændret — filen eksisterede allerede, men er blevet ændret.
  • OK — uændret siden sidst.
  • Slettet — fandtes i forrige scan, men er nu væk (slettet eller flyttet ud af mappen).

4. Klikbare links og farver

Dokumentnavnene i registret er klikbare links, der åbner filen direkte. Status-kolonnen farvelægges automatisk: grøn for nye, gul for ændrede, rød for slettede. Det giver et hurtigt overblik, selv uden at læse hver række.


Del 6 · Tilpasning

Gør det til jeres

Scriptet virker som det er — men der er to tilpasninger, der gør det endnu stærkere:

Tilpas ID-formatet

Scriptet forventer Dokument-ID'er i formatet XX-YY (fx 30-01). Bruger I et andet format — fx med tre cifre (300-001) eller med bogstaver (DOK-30-01) — skal I ændre det regulære udtryk i funktionen scanMappe. Linjen der matcher er:

Ændr ID-formatet// Standard: XX-YY (fx 30-01) var idMatch = navn.match(/^(\d{2}-\d{2})/); // Tre cifre: XXX-YYY (fx 300-001) var idMatch = navn.match(/^(\d{3}-\d{3})/); // Med præfiks: DOK-XX-YY (fx DOK-30-01) var idMatch = navn.match(/^(DOK-\d{2}-\d{2})/);

Ekstra kolonner fra dokumentindhold

Hvis jeres dokumenter følger dokumentstandarden fra Guide 1 med et fast dokumenthoved, kan scriptet udvides til at læse indholdet af Google Docs og udtrække felter som version, status og godkendt af. Det kræver en ensartet skabelon — men har I den allerede, er det en kraftig udvidelse. Det kræver mere kode og er en oplagt forbedring, når basisversionen kører stabilt.

Begrænsninger at kende

Apps Script har en eksekveringsgrænse på 6 minutter for gratis Google-konti og 30 minutter for Google Workspace. For et typisk ISO-dokumentsæt (50–300 filer) er 6 minutter rigeligt — scriptet scanner normalt 200+ filer på under 30 sekunder. Først ved 2.000–3.000 filer begynder I at nærme jer grænsen. Google Drives API-kvote er 10.000 kald pr. dag pr. bruger, hvilket også er rigeligt for daglige scans.


Del 7 · Kobling til ISO

Hvordan registret passer ind i jeres kvalitetssystem

Et selvvedligeholdende dokumentregister er ikke bare en smart teknisk løsning — det opfylder direkte kravene i ISO 9001:2015 punkt 7.5.3 (styring af dokumenteret information). Standarden kræver, at dokumenteret information er "tilgængelig og egnet til brug, når og hvor den er nødvendig". Et register, der altid er ajour, med klikbare links til hvert dokument, opfylder det krav mere pålideligt end noget manuelt system.

Konkret:

  • Jeres kvalitetshåndbog kan henvise til dokumentregistret med et link i stedet for at indeholde en statisk dokumentliste. Registret er altid gældende.
  • Jeres auditor kan åbne registret og se alle dokumenter, deres stier, ejere og seneste ændringer. Ét link besvarer de fleste spørgsmål om dokumentstyring.
  • Status-kolonnen giver jer et revisionsværktøj: se hvilke dokumenter der er ændret siden sidste audit, hvilke der er nye, og — vigtigst — hvilke der er slettet eller forsvundet.
  • Det daglige scan fungerer som en uafhængig kontrol. Hvis nogen sletter et dokument ved en fejl, fanger registret det inden for 24 timer.

Registret erstatter ikke det menneskelige ansvar for dokumentstyring — det eliminerer det manuelle arbejde, der får folk til at opgive ansvaret. Den kvalitetsansvarlige bruger tiden på at vurdere, om dokumenter er opdaterede og korrekte — ikke på at vedligeholde en liste over, hvilke dokumenter der eksisterer.


Del 8 · Afrunding

Registret er fundamentet — automatiseringen er cement

I Guide 1 byggede vi fundamentet: mappestruktur, registre og dokumentstandard. Denne guide har gjort det vigtigste af de registre — dokumentoversigten — selvvedligeholdende. Det er forskellen på et system, der kræver vedligeholdelse, og et system, der er vedligeholdelse.

Start med at køre scriptet én gang. Se resultatet. Justér, hvis noget mangler. Og sæt den daglige trigger op. Fra i morgen er jeres dokumentoversigt altid gældende — uden at I løfter en finger.

Næste skridt

Denne guide er en udvidelse til ISO-serien. Har du ikke læst Guide 1 endnu? Start med Fundamentet — saml, strukturér og standardisér din ISO-dokumentation med AI for at bygge den mappestruktur og dokumentstandard, dette register scanner. Guide 2 — Det levende system viser, hvordan du gør hele kvalitetssystemet tilgængeligt for organisationen med AI.

Kunne du lide denne guide?

Pernille Sten Kjerumgaard

Skrevet af

Pernille Sten Kjerumgaard

Jeg tror på, at kunstig intelligens ikke kun er for tekniske eksperter eller store Silicon Valley-virksomheder. AI er et værktøj, der skal ud i hænderne på sygeplejersken, tømreren og den selvstændige erhvervsdrivende for at skabe reel værdi i hverdagen. Som medstifter af HeyAI.dk er min mission at gøre det komplekse begribeligt og sikre, at ingen bliver ladt i stikken i den teknologiske revolution. Mine fokusområder: Praktisk anvendelse: Hvordan bruger du helt konkret værktøjer som ChatGPT, Claude og Midjourney til at spare tid og øge kreativiteten? Sikkerhed & Etik: Jeg navigerer i spændingsfeltet mellem innovation og compliance (GDPR/EU AI Act), så du kan bruge teknologien med ro i maven. Fremtidens arbejdsmarked: Hvordan vi bevarer det menneskelige aftryk i en automatiseret verden. Hvorfor læse med her? Når jeg skriver, er det altid i øjenhøjde. Der findes ingen dumme spørgsmål – kun dårlige forklaringer. Mit mål er at give dig de nødvendige "superkræfter", så du kan træffe oplyste valg om alt fra gratis-versioner til de tunge betalte platforme. "Det handler ikke om, hvad teknologien kan, men om hvad du kan bruge den til."

Følg på LinkedIn