Pages

Se afișează postările cu eticheta demo. Afișați toate postările
Se afișează postările cu eticheta demo. Afișați toate postările

marți, 7 iulie 2026

Google Apps Script : example of transition from a Google Sheet to a formatted Google Doc.

This script that automates the transition from a Google Sheet to a formatted Google Doc. Here is a breakdown of what this solution does:
Custom Menu Integration: The script adds a Custom Menu directly into your Google Sheet interface. With a single click, you can trigger processes like fetching data or generating reports, making the tool incredibly easy to use without touching the code.
This example is based on this URL : https://www.planetpython.org/opml.xml.
Intelligent Data Processing: It doesn't just copy text; it parses RSS and Atom feeds, extracts titles and links, and prepares them for your document. It intelligently handles the HYPERLINK formulas you use in Sheets, translating them into real, clickable links in your final document.
Automatic Folder Management: One of the most useful features of this script is its ability to keep your Drive organized. Instead of cluttering your root directory, the script automatically identifies the folder where your source spreadsheet is located and creates the new document right there.
Built-in Troubleshooting: I have included logging functionality throughout the code. If a link is malformed or a feed fails to load, the script logs exactly what happened, allowing you to debug issues quickly via the Apps Script Dashboard.
Let's see the source code for Google Apps Scripts:
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Custom Menu')
    .addItem('Read OPML PlanetPython', 'fetchAndProcessFeed')
    .addItem('Download Selected Content', 'downloadSelectedContentWrapper')
    .addItem('Send Sheet via Email', 'sendSheetViaEmail')
    .addToUi();
}

function fetchAndProcessFeed() {
  const dateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd_HH-mm");
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = spreadsheet.getSheetByName(dateTime);
  
  if (!sheet) {
    sheet = spreadsheet.insertSheet(dateTime);
  } else {
    sheet.clear();
  }
  
  sheet.appendRow(["Date", "Source", "Title", "Select"]);
  
  const opmlUrl = "https://www.planetpython.org/opml.xml";
  const opmlContent = UrlFetchApp.fetch(opmlUrl).getContentText();
  const opmlDoc = XmlService.parse(opmlContent);
  const outlines = opmlDoc.getRootElement().getChild("body").getChildren("outline");
  
  outlines.forEach(outline => {
    const text = outline.getAttribute("text")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const xmlUrl = outline.getAttribute("xmlUrl")?.getValue() || "";
    
    try {
      const feedContent = UrlFetchApp.fetch(xmlUrl).getContentText();
      const feedDoc = XmlService.parse(feedContent);
      const root = feedDoc.getRootElement();
      
      if (root.getName() === "rss") {
        processRssFeed(root, text, xmlUrl, sheet);
      } else if (root.getName() === "feed") {
        processAtomFeed(root, text, xmlUrl, sheet);
      }
    } catch (e) {
      Logger.log(`Error processing feed ${text} (${xmlUrl}): ${e}`);
    }
  });
}

function processRssFeed(root, source, xmlUrl, sheet) {
  const items = root.getChild("channel")?.getChildren("item") || [];
  items.forEach(item => {
    const title = item.getChild("title")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const pubDate = item.getChild("pubDate")?.getValue() || "";
    const link = item.getChild("link")?.getValue().replace(/[<>&]/g, '') || xmlUrl;
    sheet.appendRow([
      pubDate,
      `=HYPERLINK("${xmlUrl}", "${source}")`,
      `=HYPERLINK("${link}", "${title}")`,
      ""
    ]);
  });
}

function processAtomFeed(root, source, xmlUrl, sheet) {
  const entries = root.getChildren("entry") || [];
  entries.forEach(entry => {
    const title = entry.getChild("title")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const updated = entry.getChild("updated")?.getValue() || "";
    const link = entry.getChild("link")?.getAttribute("href")?.getValue().replace(/[<>&]/g, '') || xmlUrl;
    sheet.appendRow([
      updated,
      `=HYPERLINK("${xmlUrl}", "${source}")`,
      `=HYPERLINK("${link}", "${title}")`,
      ""
    ]);
  });
}

function downloadSelectedContentWrapper() {
  downloadSelectedContent();
}

async function downloadSelectedContent() {
  const dateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd_HH-mm");
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getActiveSheet();
  const data = sheet.getDataRange().getValues();
  const doc = DocumentApp.create(`Content_${dateTime}`);
  const folderId = DriveApp.getFileById(spreadsheet.getId()).getParents().next().getId();
  DriveApp.getFileById(doc.getId()).moveTo(DriveApp.getFolderById(folderId));
  
  let contentAdded = false;
  const body = doc.getBody();
  
  for (let i = 1; i < data.length; i++) {
    const row = data[i];
    if (row[3] == 1) {
      const sourceMatch = row[1].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const source = sourceMatch ? sourceMatch[2] : row[1].toString().replace(/[<>&]/g, '') || "Unknown source";
      const titleMatch = row[2].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const title = titleMatch ? titleMatch[2] : row[2].toString().replace(/[<>&]/g, '');
      const link = titleMatch ? titleMatch[1] : "";
      
      Logger.log(`Processing ${title} with link: ${link}`);
      
      try {
        body.appendParagraph(source).setHeading(DocumentApp.ParagraphHeading.HEADING1);
        const titleParagraph = body.appendParagraph(title).setHeading(DocumentApp.ParagraphHeading.HEADING2);
        if (link) titleParagraph.setLinkUrl(link); // Titlu ca hyperlink
        body.appendParagraph(""); // Spațiu între intrări
        contentAdded = true;
        Logger.log(`Added ${title} with link`);
      } catch (e) {
        Logger.log(`Error processing ${title} (${link}): ${e}`);
        body.appendParagraph(source).setHeading(DocumentApp.ParagraphHeading.HEADING1);
        const titleParagraph = body.appendParagraph(title).setHeading(DocumentApp.ParagraphHeading.HEADING2);
        if (link) titleParagraph.setLinkUrl(link);
        body.appendParagraph("");
        contentAdded = true;
      }
    }
  }
  
  if (!contentAdded) {
    Logger.log("No content was added to the document.");
    body.appendParagraph("No content was selected or available.");
  }
}


function sendSheetViaEmail() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getActiveSheet();
  const sheetName = sheet.getName();
  const data = sheet.getDataRange().getValues();
  
  let htmlContent = `
    <html>
      <head>
        <title>${sheetName}</title>
      </head>
      <body>
        <h1>${sheetName}</h1>
        <table border="1">
          <tr>
            <th>Date</th>
            <th>Source</th>
            <th>Title</th>
            <th>Select</th>
          </tr>
  `;
  
  data.forEach((row, index) => {
    if (index > 0) {
      const date = row[0] || "";
      const sourceMatch = row[1].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const sourceUrl = sourceMatch ? sourceMatch[1] : "";
      const sourceText = sourceMatch ? sourceMatch[2] : row[1].toString().replace(/[<>&]/g, '');
      const titleMatch = row[2].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const titleUrl = titleMatch ? titleMatch[1] : "";
      const titleText = titleMatch ? titleMatch[2] : row[2].toString().replace(/[<>&]/g, '');
      const select = row[3] || "";
      htmlContent += `
        <tr>
          <td>${date}</td>
          <td><a href="${sourceUrl}">${sourceText}</a></td>
          <td><a href="${titleUrl}">${titleText}</a></td>
          <td>${select}</td>
        </tr>
      `;
    }
  });
  
  htmlContent += `
        </table>
      </body>
    </html>
  `;
  
  const mimetype = "application/epub+zip";
  const containerXml = `
    <?xml version="1.0"?>
    <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
      <rootfiles>
        <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
      </rootfiles>
    </container>
  `;
  
  const contentOpf = `
    <?xml version="1.0" encoding="UTF-8"?>
    <package xmlns="http://www.idpf.org/2007/opf" unique-identifier="bookid" version="2.0">
      <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
        <dc:title>${sheetName}</dc:title>
        <dc:identifier id="bookid">urn:uuid:${Utilities.getUuid()}</dc:identifier>
        <dc:language>en</dc:language>
      </metadata>
      <manifest>
        <item id="content" href="content.html" media-type="application/xhtml+xml"/>
      </manifest>
      <spine>
        <itemref idref="content"/>
      </spine>
    </package>
  `;
  
  const blobs = [
    Utilities.newBlob("mimetype", "text/plain", "mimetype").setContentType(mimetype),
    Utilities.newBlob(containerXml, "application/xml", "META-INF/container.xml"),
    Utilities.newBlob(contentOpf, "application/xml", "OEBPS/content.opf"),
    Utilities.newBlob(htmlContent, "application/xhtml+xml", "OEBPS/content.html")
  ];
  
  const zipOutput = Utilities.zip(blobs, `Sheet_${sheetName}.epub`);
  
  MailApp.sendEmail({
    to: "catalinfest@gmail.com,catafest@yahoo.com",
    subject: `Sheet activ: ${sheetName}`,
    body: "Vezi atașat sheet-ul activ în format EPUB.",
    attachments: [zipOutput]
  });
}

luni, 15 iunie 2026

Google Apps Script : simple gmail manager !

Today, if you can't afford a paid Google account, you can use Google Apps Script to create your own tools to help you. Here's an older example of an email manager that labels, groups, deletes emails, etc.

vineri, 17 aprilie 2026

Google Apps Script : ... youtube script for dashboard.

Today, I tested Google Apps Script to get data from youtube dashboard, because I make some streams on youtube and another social platforms.
The source code is large, but I will show this part to understand the basics:
function getChannelStats() {
  const response = YouTube.Channels.list(
    "snippet,statistics",
    { mine: true }
  );

  const ch = response.items[0];

  return {
    title: ch.snippet.title,
    subs: Number(ch.statistics.subscriberCount),
    views: Number(ch.statistics.viewCount),
    videos: Number(ch.statistics.videoCount)
  };
} ...

vineri, 13 februarie 2026

Tools : Hypatia Zero global weather.

Zero democratizes access to the world's best weather data.
Hypatia Zero visualizes global weather in your browser using WebGPU.
ECMWF runs the world's most accurate weather model four times daily. Since October 2025, this data is openly published under CC-BY-4.0. Zero downloads it directly into your browser—no backend, no accounts, just you and the atmosphere.
Scrub through up to 2 weeks of weather. Watch storms form and dissolve. Every minute interpolated, every layer rendered on the GPU.
The source code can be found on the GitHub repo.

marți, 10 februarie 2026

News : Create Your First Gemini Enterprise Application - limited .

To use Gemini Enterprise, you are required to have:
- a custom domain
- Cloud Identity Premium or Google Workspace Enterprise
- users managed in Google Identity
- Gemini Enterprise licenses (paid)
Great product, great learning, but without a free option, these features are limited to a few people.

duminică, 1 februarie 2026

Google Apps Script : my activity on blogger with Blogger API.

Here in the attached image is an informative chart about my activity with posts on my bloggers and the completion trend. This chart was created with Google Apps Script and the Blogger API.

vineri, 9 ianuarie 2026

News : website with simulators and jokes - pranx.

Today, another website with simulators and jokes:
If you don’t pay your exorcist, do you get repossessed?
The man who invented knock-knock jokes should get a no bell prize.
I have a few jokes about unemployed people, but none of them work.
If you want to catch a squirrel just climb a tree and act like a nut.

marți, 23 decembrie 2025

Google Apps Script : ... demonstration of the chart feature.

One simple example, see this part of source code:
 // ✅ Chart cu legendă nativă și labelInLegend pentru fiecare serie
 // ✅ Chart with native legend and labelInLegend for each series
  const chart = chartSheet.newChart()
    .setChartType(Charts.ChartType.COMBO)
    .addRange(range)
    .setPosition(1, 1, 0, 0)
    .setOption("title", "BT Funds Evolution Over Time")
    .setOption("legend", { position: "right" })
    .setOption("width", 1600)
    .setOption("height", 900)
    .setOption("seriesType", "line")
    .setOption("hAxis", { title: "Date" })
    .setOption("vAxis", { title: "Value / Return (%)" })

    // ✅ LEGENDĂ NATIVĂ CU LABEL IN LEGEND
    // ✅ NATIVE LEGEND WITH LABEL IN LEGEND
    .setOption("series", {
      0: { labelInLegend: "VUAN",      color: "#1f77b4", pointSize: 5 },
      1: { labelInLegend: "30 zile",   color: "#ff7f0e", pointSize: 5 },
      2: { labelInLegend: "YTD",       color: "#2ca02c", pointSize: 5 },
      3: { labelInLegend: "365 zile",  color: "#d62728", pointSize: 5 },
      4: { labelInLegend: "3 ani",     color: "#9467bd", pointSize: 5 }
    })
See the result

marți, 11 noiembrie 2025

News : itch.io website with godot shader example demo.

Itch.io (stylized in all lowercase) is a website for users to host, sell and download indie video games, indie role-playing games, game assets, comics, zines and music. Launched in March 2013 by Leaf Corcoran, the service hosts over 1,000,000 products as of November 2024. See the wikipedia article.
Example of godot xe1a - itch.io website.

marți, 28 octombrie 2025

News : Inpaint4Drag framework with Google Colab demo.

Inpaint4Drag introduces a novel framework that decomposes drag-based editing into pixel-space bidirectional warping and image inpainting. Our method achieves real-time warping previews (0.01s) and efficient inpainting (0.3s) at 512×512 resolution, significantly improving interaction experience while serving as an adapter for any inpainting model.

News : Smallest 64-bit Operating System in the World! by Datastream

This 64-bit operating system is less than 1.44MB in size, as it is running entirely off of a Floppy disk. It is called MenuetOS.

joi, 24 aprilie 2025

News : Chaos destructibles drive fluidsim in Unreal Engine, NinjaLIVE 2.0 pre-alpha

  • Chaos destructibles drive fluidsim: dust & dambreak tests, NinjaLIVE 2.0 pre-alpha, Unreal Engine
  • Ninja could access Chaos mesh chunk data three ways:
  • 1. get chunk position data via Niagara Chaos Destruction DI
  • 2. get chunk SDF data via Niagara GeometryCollections DI
  • 3. get chunk pos via Blueprint, write to DataChannel, read DataChannel in Niagara

sâmbătă, 21 septembrie 2024

vineri, 23 august 2024

News : Cyberpunk 2077 goes Hyper-Realistic ... 8K video demo real!

This is an 8K video ... see on NextGenDreams - youtube channel !
They have this hardware:
Everything is recorded on this system:
Chassi: NZXT Elite H5 Black
MB: NZXT Z790 Black
GPU: Nvidia Geforce RTX 4090 (MSI SUPRIM)
CPU: Intel Core i9-13900KS
RAM: Corsair 64GB DDR 5 6000MHz CL30
Cooling System: NZXT Kraken Elite 240 Black
SSD: Samsung 990 PRO M.2 NVMe 2TB

sâmbătă, 20 iulie 2024

duminică, 7 iulie 2024