Fără programare

Datele firmelor direct în foaia ta de calcul

Registrul, TVA, adresa și bilanțul oricărei firme din România, cu o formulă în Google Sheets, cu Power Query în Excel sau într-un flux automat în Zapier, Make și n8n. Ai nevoie doar de o cheie API.

Formule noi în Google Sheets

  1. 1Deschide foaia în Google Sheets și alege Extensii > Apps Script.
  2. 2Șterge ce e acolo, lipește scriptul de alături și salvează (Ctrl+S).
  3. 3Reîncarcă foaia: apare meniul „FirmeAPI”. Alege „Setează cheia API” și lipește cheia ta.
  4. 4Scrie în orice celulă =FIRMA("33741906"; "denumire").

Ce poți scrie

  • =FIRMA("33741906"; "denumire")

    Numele firmei

  • =FIRMA(A2; "stare")

    Starea din registru, pentru CUI-ul din A2

  • =FIRMA(A2; "adresa_sediu_social.judet")

    Câmpurile din interior, cu puncte

  • =FIRMA(A2; "tva.platitor")

    Plătitor de TVA (TRUE / FALSE)

  • =BILANT(A2; "cifra_afaceri")

    Cifra de afaceri din ultimul an depus

  • =BILANT(A2; "profit_net"; 2023)

    Profitul net pe 2023

  • =FIRMEAPI("caen/" & A2; "caen_principal.cod")

    Orice rută din documentație, orice câmp

Indicatori pentru BILANT: cifra_afaceri, venituri_totale, cheltuieli_totale, profit_brut, profit_net, datorii, capitaluri, active_imobilizate, active_circulante, angajati (sau codul, ex. I13). Răspunsurile se țin minte 6 ore, ca recalcularea foii să nu consume credite.

firmeapi-google-sheets.gsDescarcă
/**
 * FirmeAPI.ro pentru Google Sheets
 *
 * Formule noi in foaia ta:
 *   =FIRMA("33741906"; "denumire")                 orice camp din datele firmei
 *   =FIRMA("33741906"; "adresa_sediu_social.judet") campurile din interior, cu puncte
 *   =BILANT("33741906"; "cifra_afaceri")           ultimul an depus
 *   =BILANT("33741906"; "profit_net"; 2023)        un an anume
 *   =FIRMEAPI("restante/33741906"; "")             orice ruta din documentatie, orice camp
 *
 * Instalare: Extensii > Apps Script, lipesti acest cod, salvezi, apoi din
 * meniul „FirmeAPI” al foii alegi „Seteaza cheia API”. Cheia ramane in contul
 * tau Google (proprietatile utilizatorului), nu in foaie.
 *
 * Raspunsurile se tin minte 6 ore: aceeasi formula, recalculata, nu consuma
 * credite de fiecare data.
 */

var FIRMEAPI_ADRESA = 'https://www.firmeapi.ro/api/v1/';
var FIRMEAPI_CACHE_SECUNDE = 6 * 60 * 60;

// Indicatorii din bilant, dupa denumirea lor (codurile I1…I20 difera dupa tipul formularului).
var FIRMEAPI_INDICATORI = {
  cifra_afaceri: /cifra de afaceri/,
  venituri_totale: /venituri totale/,
  cheltuieli_totale: /cheltuieli totale/,
  profit_brut: /profit brut/,
  pierdere_bruta: /pierdere bruta/,
  profit_net: /profit net/,
  pierdere_neta: /pierdere neta/,
  active_imobilizate: /active imobilizate/,
  active_circulante: /active circulante/,
  stocuri: /stocuri/,
  creante: /creante/,
  casa_banci: /casa/,
  datorii: /datorii/,
  capitaluri: /capitaluri/,
  angajati: /salariati/,
};

function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('FirmeAPI')
    .addItem('Setează cheia API', 'firmeapiSeteazaCheia')
    .addItem('Golește memoria (recitește datele)', 'firmeapiGolesteMemoria')
    .addToUi();
}

function firmeapiSeteazaCheia() {
  var ui = SpreadsheetApp.getUi();
  var r = ui.prompt('Cheia API FirmeAPI', 'O găsești în contul tău, la „Chei API”.', ui.ButtonSet.OK_CANCEL);
  if (r.getSelectedButton() === ui.Button.OK) {
    PropertiesService.getUserProperties().setProperty('FIRMEAPI_CHEIE', r.getResponseText().trim());
    ui.alert('Gata. Formulele =FIRMA(...) și =BILANT(...) folosesc acum cheia ta.');
  }
}

function firmeapiGolesteMemoria() {
  PropertiesService.getUserProperties().setProperty('FIRMEAPI_GENERATIE', String(Date.now()));
  SpreadsheetApp.getUi().alert('Gata. Formulele vor citi din nou datele (consumă credite).');
}

/**
 * Un camp din datele firmei (registru, ANAF, TVA, adresa).
 *
 * @param {string} cui CUI-ul firmei, cu sau fara RO
 * @param {string} camp ex. denumire, stare, cod_caen, nr_reg_com, adresa, tva.platitor, adresa_sediu_social.judet
 * @return valoarea
 * @customfunction
 */
function FIRMA(cui, camp) {
  return firmeapiCampul(firmeapiCere('firma/' + firmeapiCui(cui)).data, camp || 'denumire');
}

/**
 * Un indicator din bilantul unei firme.
 *
 * @param {string} cui CUI-ul firmei
 * @param {string} camp ex. cifra_afaceri, profit_net, venituri_totale, datorii, capitaluri, angajati, sau un cod (I13)
 * @param {number} an optional: anul bilantului; fara el, ultimul an depus
 * @return valoarea
 * @customfunction
 */
function BILANT(cui, camp, an) {
  var ani = (firmeapiCere('bilant/' + firmeapiCui(cui)).data || {}).ani || {};
  var lista = Object.keys(ani).map(function (k) { return ani[k]; }).filter(function (a) { return a && a.an; });
  if (!lista.length) throw new Error('Firma nu are bilanțuri depuse.');
  lista.sort(function (a, b) { return b.an - a.an; });

  var bilant = an ? lista.filter(function (a) { return String(a.an) === String(an); })[0] : lista[0];
  if (!bilant) throw new Error('Nu există bilanț pe ' + an + '.');

  var cheie = String(camp || '').trim();
  if (cheie === 'an' || cheie === 'denumire' || cheie === 'caen' || cheie === 'denumire_caen') return bilant[cheie];

  var tipar = FIRMEAPI_INDICATORI[cheie.toLowerCase()];
  var detalii = bilant.detalii || [];
  for (var i = 0; i < detalii.length; i++) {
    var d = detalii[i];
    var nume = firmeapiFaraDiacritice(d.val_den_indicator || '');
    if ((tipar && tipar.test(nume)) || String(d.indicator).toUpperCase() === cheie.toUpperCase()) return d.val_indicator;
  }
  throw new Error('Indicatorul „' + camp + '” nu există în bilanțul pe ' + bilant.an + '.');
}

/**
 * Orice ruta din API, orice camp din raspuns.
 *
 * @param {string} ruta ex. "restante/33741906" sau "caen/33741906"
 * @param {string} cale campul, cu puncte: ex. "caen_principal.cod"; gol = tot raspunsul, ca text
 * @return valoarea
 * @customfunction
 */
function FIRMEAPI(ruta, cale) {
  var data = firmeapiCere(String(ruta).replace(/^\/+/, '').replace(/^(api\/)?v1\//, '')).data;
  if (!cale) return JSON.stringify(data);
  return firmeapiCampul(data, cale);
}

/* ── Intern ─────────────────────────────────────────────────────────── */

function firmeapiCui(cui) {
  var c = String(cui).replace(/\D/g, '');
  if (!c) throw new Error('CUI lipsă sau greșit.');
  return c;
}

function firmeapiFaraDiacritice(s) {
  return String(s).toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '');
}

function firmeapiCampul(data, cale) {
  var v = String(cale).split('.').reduce(function (o, k) { return o == null ? null : o[k]; }, data);
  if (v === undefined) throw new Error('Câmpul „' + cale + '” nu există în răspuns.');
  return v != null && typeof v === 'object' ? JSON.stringify(v) : v;
}

function firmeapiCere(ruta) {
  var p = PropertiesService.getUserProperties();
  var cheie = p.getProperty('FIRMEAPI_CHEIE');
  if (!cheie) throw new Error('Setează cheia: meniul FirmeAPI > Setează cheia API.');

  var cache = CacheService.getUserCache();
  var cheieCache = 'f:' + (p.getProperty('FIRMEAPI_GENERATIE') || '0') + ':' + ruta;
  var tinut = cache.get(cheieCache);
  if (tinut) return JSON.parse(tinut);

  var r = UrlFetchApp.fetch(FIRMEAPI_ADRESA + ruta, {
    headers: { 'X-API-KEY': cheie, Accept: 'application/json' },
    muteHttpExceptions: true,
  });
  var corp = r.getContentText();
  var json;
  try { json = JSON.parse(corp); } catch (e) { throw new Error('Răspuns neașteptat (' + r.getResponseCode() + ').'); }
  if (r.getResponseCode() >= 400 || json.success === false) {
    throw new Error((json.error && (json.error.message || json.error)) || json.message || ('Eroare ' + r.getResponseCode()));
  }
  if (corp.length < 90000) cache.put(cheieCache, corp, FIRMEAPI_CACHE_SECUNDE);
  return json;
}