إذا بقيت البيانات داخل الجدول، فإن GOOGLEFINANCE هو الطريق الأقصر. وعندما تحتاج إلى واجهة API لتطبيقك، يمكن أن يكون Apps Script حلاً احتياطياً.
- استخدم GOOGLEFINANCE للقيمة الحالية والفترة التاريخية.
- لا يمكن قراءة بيانات GOOGLEFINANCE التاريخية من Sheets API أو Apps Script.
- تستطيع دالة FXRATE المخصصة استدعاء JSON واستخدام التخزين المؤقت.
- لا تضع مفتاح API في Apps Script لجدول مشترك.
- احتفظ بالمصدر ووقت الرصد عند عرض القيمة.
احصل على مفتاح API مجاني
سجّل في exchangerate.dev/signup. بعد تأكيد البريد تعرض لوحة التحكم مفتاحًا يبدأ بـexr_live_. انسخه؛ ستلصقه في Apps Script بعد قليل. الخطة المجانية 5,000 استدعاء شهريًا دون بطاقة.
افتح Apps Script من جدولك
افتح أي جدول في Google Sheets. من القائمة، اضغط الإضافات ← Apps Script. يفتح تبويب جديد فيه دالة function myFunction() {} افتراضية. احذف محتواها, ستستبدله في الخطوة التالية.
الصق دالة FXRATE
استبدل محتوى المحرر بهذه الدالة. تستدعي exchangerate.dev، وتخزّن كل زوج مؤقتًا لعشر دقائق عبر CacheService، وتعيد علامة مقروءة للخطأين الممكنين (401 و429).
استخدم =FXRATE() في أي خلية
ارجع إلى الجدول واكتب =FXRATE("USD","EUR") في خلية فارغة. بعد ثانية تقريبًا تعرض الخلية السعر الحالي. الدالة نفسها تعمل مع أي زوج مدعوم, بدّل رمزي العملتين:
خلف الكواليس يعيد كل استدعاء عملة الأساس، والزوج الذي رشّحت عليه، وحقلي حداثة, source وmarket_session, فتعرف دائمًا مدى حداثة الرقم:
ينشر exchangerate.dev خادم MCP وملف llms.txt، فيستطيع Claude أو Cursor أو ChatGPT قراءة المخطط الحي وكتابة الدالة نيابة عنك. اطلب منه: «ابنِ دالة مخصصة في Google Sheets باسم FXRATE تأخذ عملة مصدر وعملة هدف وتعيد السعر الحي من exchangerate.dev، مع تخزين مؤقت لعشر دقائق». راجع دليل MCP.
التحديث والاستيعاب ضمن الخطة المجانية
لا يعيد Apps Script تشغيل الدوال المخصصة بمؤقت من تلقاء نفسه. للتحديث الدوري، أضف مشغّلًا زمنيًا: من الشريط الأيسر في Apps Script اضغط المشغّلات ← إضافة مشغّل، واختر FXRATE، والمصدر مستند إلى الوقت، ثم مؤقت بالدقائق. التخزين المؤقت لعشر دقائق مع الحصة السخية يبقي المصنّف المزدحم في أمان:
- 5,000 استدعاء شهريًا، 10 طلبات في الدقيقة، دون بطاقة
- يعيد
CacheServiceالسعر المخزّن لمدة 10 دقائق، فلا تكلّف التعديلات المتكررة شيئًا - ارفع
CACHE_TTLإذا لامس جدول بأزواج كثيرة حدّ الدقيقة - يغطي
/v1/latestو/v1/convertو/v1/rangeو/v1/{date}/{base}
| الرمز | العَرَض | المعالجة |
|---|---|---|
| 401 | تعرض الخلية #AUTH_ERROR | المفتاح مفقود أو غير صالح. أعد نسخه من لوحة التحكم إلى API_KEY في أعلى Code.gs. |
| 429 | تعرض الخلية #RATE_LIMIT | تجاوزت حد الدقيقة. عادةً يمنع التخزين المؤقت ذلك؛ ارفع CACHE_TTL، أو ارتقِ بالخطة من /pricing. |
| — | تعرض الخلية #NO_PAIR | لم ترد عملة الهدف في الرد. تحقق أن الرمز عملة ISO مدعومة (مثل JPY لا JYP). |
| — | تبقى الخلية على Loading… | يحتاج Apps Script إلى إذن الطلبات الخارجية. شغّل الدالة مرة من شريط أدوات المحرر ليظهر الطلب، ثم اقبله. |
تُنشر هذه الأسعار للنمذجة والتحليل والعرض. ليست تسعيرة تداول, لا تستخدمها لتسوية صفقة أو تحويل. يذكر كل رد ذلك في حقل notice الخاص به.
ابدأ بـ GOOGLEFINANCE
استخدم =GOOGLEFINANCE("CURRENCY:USDEUR") للقيمة الحالية، وأضف تاريخ البداية والنهاية وDAILY للسلسلة اليومية. قد تتأخر الأسعار، ولا يتاح التاريخ عبر Sheets API أو Apps Script.
=GOOGLEFINANCE("CURRENCY:USDEUR")=GOOGLEFINANCE("CURRENCY:USDEUR", "price", DATE(2026, 1, 1), DATE(2026, 1, 31), "DAILY")// google-sheets: Apps Script Code.gsconst CACHE_TTL = 600; // Cache successful responses for 10 minutes./** * Returns an indicative exchange rate for one currency pair. * @param {string} from Three-letter base currency code. * @param {string} to Three-letter quote currency code. * @return {number|string} The rate or a readable error marker. * @customfunction */function FXRATE(from, to) { from = (from || 'USD').toString().trim().toUpperCase(); to = (to || 'EUR').toString().trim().toUpperCase(); if (!/^[A-Z]{3}$/.test(from) || !/^[A-Z]{3}$/.test(to)) return '#NO_PAIR'; const cacheKey = `fx_${from}_${to}`; const cache = CacheService.getScriptCache(); const cached = cache.get(cacheKey); if (cached) return Number(cached); const url = `https://api.exchangerate.dev/v1/latest/${from}?symbols=${to}`; let resp; try { resp = UrlFetchApp.fetch(url, { muteHttpExceptions: true }); } catch { return '#FETCH_ERROR'; } const code = resp.getResponseCode(); if (code === 401 || code === 403) return '#ACCESS_ERROR'; if (code === 429) return '#RATE_LIMIT'; if (code !== 200) return '#ERROR'; let data; try { data = JSON.parse(resp.getContentText()); } catch { return '#INVALID_RESPONSE'; } const rate = data && data.rates && data.rates[to]; if (rate == null) return '#NO_PAIR'; if (typeof rate !== 'number' || !Number.isFinite(rate) || rate <= 0) return '#INVALID_RESPONSE'; cache.put(cacheKey, String(rate), CACHE_TTL); return Number(rate); // coerce so cells sum and sort}// Euro per US dollar=FXRATE("USD", "EUR") // 0.9245// Japanese yen per US dollar=FXRATE("USD", "JPY") // 157.32// British pound per euro=FXRATE("EUR", "GBP") // 0.8531// Indonesian rupiah per US dollar=FXRATE("USD", "IDR") // 16285.0{ "result": "success", "base": "USD", "source": "live", "market_session": "open", "timestamp": "2026-06-29T09:14:02Z", "data_updated_at": "2026-06-29T09:14:00Z", "rates": { "JPY": 157.32 }, "sources": { "JPY": "live" }, "notice": "Indicative rates, not for settlement."}=FXRATE("USD", "EUR")