Node.js ile Excel'den, Barkod Etiketi Nasıl Yazdırılır ?
Amacımız, Excel dosyasının (.xlsx) her bir satırı için barkod yazıcıdan bir etiket çıkartmak. Bu uygulama, birçok iş alanında veya sektörde kullanılmaktadır. Bu küçük yazılım projesi için, projede kullanmak üzere bu linkte bulunan excel dosyasını indirdim. İlk kolonu dosyaya ekledim. Dosya aşağıdaki hale geldi.. İlk satırı yani başlıkları da resimdeki gibi değiştirdim.
Yalnız barkod bilgisini yazıcıya yollarken başında bulunan # işaretini ayıklamak gerekiyor. Bunu, node.js programında hallediyor olacağız.
Bu komut ile baskı işlemi, id'si 1 olan etiketten başlanacak, 50 olanda son bulacak demektir. 2. parametre kullanılmasaydı, 1'den sona kadar etiket basılacaktı.
Eğer Node.js bilgisayarda kurulmuş ise proje klasörüne girerek, aşağıdaki komutları, komut isteminde (cmd) yazabiliriz. Node.js’in daha önceden bilgisayara kurulup kurulmadığını anlamak için
Bu komutları yazarken, bilgisayar internete bağlı olmalıdır.node -v
komutunu deneyebilirsiniz.
node init -y
node install xlsx
Videoda kullandığım, yani etiket tasarım programının eski sürümünü (Nicelabel 5.2), linkteki yazımda, 4. paragrafta bulabilirsiniz. Nicelabel’ın daha yeni sürümü de, o yazıda ilk paragrafta yer alıyor. O yazıda yeni sürüm Nicelabel ile, etiket şablonunu nasıl elde edeceğimizi anlatmıştım. Eski sürümü kullanmak çok daha kolay. Yani Nicelabel’ı sadece şablon dosyasını kolayca oluşturmak için kullanıyoruz.
Etiket şablonunu (template.txt) ve excel dosyasını proje dizinine koymamız gerekiyor. Node.js programının, excel'den çekip etikete yerleştireceği değişken alanları süslü parantezler ile tanımlıyoruz.
template.txt :
#!A1#DC
#IMSR50.00/50.00
#RX0
#ERN/1//0
#R0/0
#T02.00 #J02.08 #YB2/0P2.0M/12.25/5///{{UPC}}#G
#T02.00 #J21.16 #YN101/0/38///{{Type}}#G
#T02.00 #J32.91 #YN101/0/38///{{Product}}#G
#T02.00 #J26.00 #YN101/0B/51///TYPE :#G
#T02.00 #J37.91 #YN101/0B/51///PRODUCT :#G
#T11.33 #J43.66 #YN101/0/51///{{id}}#G
#T02.00 #J43.66 #YN101/0B/51///ID :#G
#Q1#G
#!P1
Bu proje sadece Novexx yazıcılara özeldir diye düşünmeyin. Örneğin Zebra yazıcı için kullanacaksak, şablon dosyasını easyplug değil, zpl ile hazırlamak yeterli olacaktır. Bir de Zebra’nın sorgulama komutuna (~HS) göre node.js programını düzenlemek gerekecektir haliyle.
Hercules programında TCP server sekmesini, test amacıyla, yazıcının yerine kullanabiliyoruz. Yani yazıcı, Hercules olmuş oluyor. Böylece, yaptığınız yazılım veya plc’den yazıcıya ne yolladığınızı görmek mümkün oluyor. Youtube videosunda da bu şekilde yaptım zaten, gerçek yazıcı yerine Hercules’i çalıştırdım.
Eskiden birisi excel’den etiket basmak istiyorum dediğinde ona Nicelabel Express sürümünü önerirdik. Belli bir ücret karşılığında alır tepe tepe kullanırdı. Ama artık malesef durumlar değişti. Nicelabel artık yıllık abonelik sistemine geçti. Yani bu yazılımın bedeli olarak bir kere ödeme yapmanız yeterli olmuyor, her yıl ödeme yapmanız isteniyor. Bu mini node projesini yazmak için bu sayede motive oldum diyebilirim. Bu tip basit bir iş için neden yıllık abonelik filan gereksin ki ? Kendi kodumuzu node.js ile oluşturup, tepe tepe, ücretsiz olarak kullanabiliriz. Chatgpt sayesinde yazılım yapmak artık daha kolay hale gelmişken, bu projeyi oluşturmak çok da zor olmadı açıkçası.
Benim gibi yazılımcı değilsiniz ama ufak tefek yazılım işleriniz görülsün istiyorsanız, node.js tam size göre diyebilirim. Binlerce gönüllü yazılımcı, npmjs.org sitesine hangi paketi yazsam da işe yarayan bir kütüphane oluştursam diye uğraşıyor. Bize de oradan bir paketi, npm install ile bilgisayara yükleyip kullanmak kalıyor. Bir hayırsever xlsx paketini yazmış, onu kullandık. Excel dosyalarını okuyan tek paket bu diye düşünmeyin, bu onlardan birisi sadece. Exceljs paketi de sık kullanılıyor. Birçok yaralı parmağa işemeyen insan, nasıl olur da bir ecnebi hayır işler bunu bir türlü anlayamıyor. Nasıl olur da bu tip yazılımları, insanlığa ücretsiz sunarlar ? Bilmezler ki açık kaynaklı yazılım, yazılımın özgürlüğüdür aslında. Sebeb, belki de insanları aylık abonelik ücretleriyle haraca bağlayan yazılım devlerine bir göz kırpmaktır, kim bilir.
Programı çalıştırmak için :
node print-label 1 50
print-label.js :
const fs = require('fs');
const net = require('net');
const xlsx = require('xlsx'); // npm install xlsx
const PRINTER_IP = '127.0.0.1'; // Yazıcınızın IP adresi
const PRINTER_PORT = 9100;
// Yazıcı sorgulama, hafızadaki etiket sayısını geri döndürür
const STATUS_COMMAND = '#!A1#!XM1007';
const EXCEL_FILE = 'labels.xlsx'
// Etiket şablonu (EasyPlug dosyası)
const TEMPLATE_FILE = 'template.txt'
// Yazıcının sorgulamaya cevap vermesi gecikirse kullanılır
const RESPONSE_TIMEOUT = 3000
// Her bu süre dolduğunda yazıcı sorgulanır
const POLLING_INTERVAL = 5000
// Hafızada 5 veya daha az etiket kalırsa, tekrar etiket yollanır
const LABELS_IN_QUEUE = 5
// Yazıcıya ilk gönderimde, yollanacak etiket sayısı
const LABELS_QTY_FIRST_PRINT = 15
// Tek seferde yollanacak etiket adedi
const LABELS_QTY_TO_SEND = 10
let connection;
let pollingInterval;
let fullLabelData = []; // Tüm Excel verisi
let labelQueue = []; // Belirlenen aralıktaki etiketler
let sentIndex = 0;
let labelTemplate = '';
// 👉 Komut satırı argümanlarını al
const args = process.argv.slice(2);
const startRow = parseInt(args[0]) || 1; // 1. parametre: başlangıç satırı
const endRow = args[1] ? parseInt(args[1]) : null; // 2. parametre: bitiş satırı (opsiyonel)
// 📄 Excel'den verileri oku ve filtrele
function loadLabelsFromExcel() {
const workbook = xlsx.readFile(EXCEL_FILE);
const sheetName = workbook.SheetNames[0];
const sheet = workbook.Sheets[sheetName];
fullLabelData = xlsx.utils.sheet_to_json(sheet);
const startIndex = startRow - 1; // Kullanıcı 1 ile başlatır, dizi 0 tabanlı
const endIndex = endRow ? endRow : fullLabelData.length;
labelQueue = fullLabelData.slice(startIndex, endIndex); // Basılacak etiketler
console.log(`\n✅ Excel'den satır ${startRow} - ${endRow || fullLabelData.length} arası yüklendi (${labelQueue.length} etiket).`);
}
// 🧾 Etiket şablonunu oku
function loadTemplate() {
labelTemplate = fs.readFileSync('template.txt', 'utf-8');
console.log(`\n🧩 Etiket şablonu yüklendi.`);
}
// 🔄 Şablonu verilerle doldur
function applyDataToTemplate(data) {
return labelTemplate.replace(/{{(.*?)}}/g, (_, key) => {
const trimmedKey = key.trim();
let value = data[trimmedKey] || '';
// Eğer barkod alanı ise baştaki # karakterini kaldır
if (trimmedKey.toLowerCase() === 'upc') {
value = value.startsWith('#') ? value.slice(1) : value;
}
return value;
});
}
// 📤 Etiket gönder
function sendLabels(count) {
let sent = 0;
while (sent < count && sentIndex < labelQueue.length) {
const data = labelQueue[sentIndex];
const filledLabel = applyDataToTemplate(data);
connection.write(filledLabel);
sent++;
sentIndex++;
}
console.log(`\n➡️ ${sent} etiket gönderildi. Toplam gönderilen: ${sentIndex}`);
}
// 🔍 Yazıcıyı sorgula
let responseTimeout;
function queryPrinterStatus() {
if (connection && !connection.destroyed) {
connection.write(STATUS_COMMAND);
// RESPONSE_TIMEOUT ms içinde cevap gelmezse sonlandır
responseTimeout = setTimeout(() => {
console.error(`\n⏱️ Yazıcıdan ${RESPONSE_TIMEOUT} ms içinde cevap gelmedi. Program sonlandırılıyor.\n`);
connection.destroy(); // bağlantıyı kapat
stopPolling();
process.exit(1);
}, RESPONSE_TIMEOUT);
}
}
// 🧠 Yazıcı cevabını işle
function handlePrinterResponse(data) {
clearTimeout(responseTimeout); // timeout'u iptal et
const response = data.toString().trim();
const labelsInQueue = parseInt(response);
if (!isNaN(labelsInQueue)) {
console.log(`📋 Yazıcıda bekleyen etiket sayısı: ${labelsInQueue}`);
// Eğer yazıcı kuyruğu 5 veya daha azsa, sıradaki 10 etiketi gönder
if (labelsInQueue <= LABELS_IN_QUEUE && sentIndex < labelQueue.length) {
sendLabels(LABELS_QTY_TO_SEND);
}
// Eğer tüm etiketler gönderildi ve yazıcı kuyruğu boşsa
if (sentIndex >= labelQueue.length && labelsInQueue === 0) {
console.log('\n✅ Tüm etiketler yazdırıldı. Program kapanıyor.\n');
stopPolling();
connection.end();
}
} else {
console.warn(`⚠️ Yazıcıdan sayı formatında cevap alınamadı: ${response}`);
}
}
// 🔌 Yazıcıya bağlan
function connectToPrinter() {
connection = new net.Socket();
connection.connect(PRINTER_PORT, PRINTER_IP, () => {
console.log("🔗 Yazıcıya bağlandı.");
sendLabels(LABELS_QTY_FIRST_PRINT); // İlk gönderim
startPolling();
});
connection.on('data', handlePrinterResponse);
connection.on('error', (err) => {
console.error("❌ Yazıcı bağlantı hatası:", err.message);
stopPolling();
});
connection.on('close', () => {
console.log("🔌 Bağlantı kapandı.\n");
stopPolling();
});
}
function startPolling() {
pollingInterval = setInterval(queryPrinterStatus, POLLING_INTERVAL);
}
function stopPolling() {
if (pollingInterval) clearInterval(pollingInterval);
}
// ▶️ Başlat
loadTemplate();
loadLabelsFromExcel();
connectToPrinter();
Yorumlar
Yorum Gönder