Il Code 39 è un codice a barre che nasce nel 1974 per l’esigenza di avere una catalogazione alfanumerica nella matricola dei prodotti di magazzino ed ancora oggi è molto utilizzato, soprattutto in campo industriale. In questo articolo vedremo di capire gli aspetti teorici di questo tipo di barcode e poi svilupperemo insieme un algoritmo per codificarlo in linguaggio C++, utilizzando le MFC.
Il Code 39 utilizza 43 caratteri alfanumerici, le lettere maiuscole dell’alfabeto, i numeri ed alcuni caratteri speciali come lo spazio, il punto, il trattino, il dollaro, il segno più, lo slash e il simbolo della percentuale. Il carattere speciale asterisco invece serve per iniziare e terminare il codice. C’è anche un carattere di controllo che si ottiene dal modulo 43 della somma dei precedenti valori secondo una tabella che analizzeremo più tardi quando affronteremo la creazione dell’algoritmo di codifica. Per disegnare il codice a barre dobbiamo sapere che, nel Code 39 ogni elemento è composto da 9 elementi, 5 barre e 4 spazi e di questi, 3 sono larghi e 6 stretti. Capirete da questo che l’estensione del disegno è molto più grande rispetto alla codifica EAN, infatti nel mio programma ho dovuto raddoppiare gli spazi necessari.
Veniamo quindi a buttar giù un po’ di righe per l’algoritmo in C++ per codificare il Code 39. Come prima funzione che dobbiamo implementare c’è quella per trovare il carattere di controllo, ossia il modulo 43 del totale dei pesi degli altri elementi del codice:
CStringArray arrVal; arrVal.Add(_T("0")); arrVal.Add(_T("1")); arrVal.Add(_T("2")); ... arrVal.Add(_T("8")); arrVal.Add(_T("9")); arrVal.Add(_T("A")); arrVal.Add(_T("B")); arrVal.Add(_T("C")); ... arrVal.Add(_T("Y")); arrVal.Add(_T("Z")); arrVal.Add(_T("-")); arrVal.Add(_T(".")); arrVal.Add(_T(" ")); arrVal.Add(_T("$")); arrVal.Add(_T("/")); arrVal.Add(_T("+")); arrVal.Add(_T("%")); int iTot = 0; for (int i = 0; i < strValue.GetLength(); ++i) { for (int j = 0; j < arrVal.GetCount(); ++j) { if (arrVal.GetAt(j) == strValue.GetAt(i)) { iTot += j; } } } div_t dv = div(iTot, 43); strValue = arrVal.GetAt(dv.rem); arrVal.RemoveAll(); return (char)strValue[0];
Nell’array ho inserito i caratteri in ordine al loro peso, quindi la lettera A in posizione 11 ed il simbolo di percentuale il valore 42. Alla fine si prende la somma ottenuta e si fa il modulo 43 di questa cifra, il resto restituito equivale al carattere corrispondente, quello di controllo.
Per il disegno dobbiamo rifarci ad una tabella tra righe piene e vuote che memorizziamo in un array:
CMapStringToString mapDraw; mapDraw.InitHashTable(44); mapDraw.SetAt(_T("1"), _T("100100001")); mapDraw.SetAt(_T("2"), _T("001100001")); mapDraw.SetAt(_T("3"), _T("101100000")); mapDraw.SetAt(_T("4"), _T("000110001")); mapDraw.SetAt(_T("5"), _T("100110000")); mapDraw.SetAt(_T("6"), _T("001110000")); mapDraw.SetAt(_T("7"), _T("000100101")); mapDraw.SetAt(_T("8"), _T("100100100")); mapDraw.SetAt(_T("9"), _T("001100100")); mapDraw.SetAt(_T("0"), _T("000110100")); mapDraw.SetAt(_T("A"), _T("100001001")); mapDraw.SetAt(_T("B"), _T("001001001")); mapDraw.SetAt(_T("C"), _T("101001000")); mapDraw.SetAt(_T("D"), _T("000011001")); mapDraw.SetAt(_T("E"), _T("100011000")); mapDraw.SetAt(_T("F"), _T("001011000")); mapDraw.SetAt(_T("G"), _T("000001101")); mapDraw.SetAt(_T("H"), _T("100001100")); mapDraw.SetAt(_T("I"), _T("001001100")); mapDraw.SetAt(_T("J"), _T("000011100")); mapDraw.SetAt(_T("K"), _T("100000011")); mapDraw.SetAt(_T("L"), _T("001000011")); mapDraw.SetAt(_T("M"), _T("101000010")); mapDraw.SetAt(_T("N"), _T("000010011")); mapDraw.SetAt(_T("O"), _T("100010010")); mapDraw.SetAt(_T("P"), _T("001010010")); mapDraw.SetAt(_T("Q"), _T("000000111")); mapDraw.SetAt(_T("R"), _T("100000110")); mapDraw.SetAt(_T("S"), _T("001000110")); mapDraw.SetAt(_T("T"), _T("000010110")); mapDraw.SetAt(_T("U"), _T("110000001")); mapDraw.SetAt(_T("V"), _T("011000001")); mapDraw.SetAt(_T("W"), _T("111000000")); mapDraw.SetAt(_T("X"), _T("010010001")); mapDraw.SetAt(_T("Y"), _T("110010000")); mapDraw.SetAt(_T("Z"), _T("011010000")); mapDraw.SetAt(_T("-"), _T("010000101")); mapDraw.SetAt(_T("."), _T("110000100")); mapDraw.SetAt(_T(" "), _T("011000100")); mapDraw.SetAt(_T("*"), _T("010010100")); mapDraw.SetAt(_T("$"), _T("010101000")); mapDraw.SetAt(_T("/"), _T("010100010")); mapDraw.SetAt(_T("+"), _T("010001010")); mapDraw.SetAt(_T("%"), _T("000101010"));
Ogni carattere ha nove numeri tra 0 ed 1, in posizioni dispari, il primo indica il disegno di uno linea larga e lo 0 di una linea stretta, per i pari rispettivamente uno spazio largo ed uno stretto. A questo punto è semplice fare il disegno, qui per questioni di lungaggini ho inserito solo l’algoritmo per disegnare il codice a barre, ovviamente ognuno si può inventare la sua procedura:
CString strTemp; for (int i = 0; i < m_strCodix.GetLength(); ++i) { strTemp = m_strCodix.GetAt(i); if (mapDraw.Lookup(strTemp, buffer)) { for (j = 1; j <= 9; ++j) { if ((j % 2) != 0) { dc.MoveTo(counter, rectCodix.top); if (buffer.Mid(j - 1, 1) == _T("1")) { dc.LineTo(counter, rectCodix.bottom); counter++; dc.MoveTo(counter, rectCodix.top); dc.LineTo(counter, rectCodix.bottom); counter++; dc.MoveTo(counter, rectCodix.top); dc.LineTo(counter, rectCodix.bottom); } else dc.LineTo(counter, rectCodix.bottom); counter++; } else { if (buffer.Mid(j - 1, 1) == _T("1")) counter += 3; else counter++; } } }
La procedura è semplice, basta infatti iterare il valore alfanumerico del codice a barre e trovare il valore corrispondente nella map, a quel punto sapremo le linee e gli spazi che dobbiamo inserire. Ovviamente non dimenticate di inserire l’asterisco iniziale e finale.
Il codice a barre Code 39 è molto semplice da implementare, conoscendo gli aspetti teorici. Questo tipo di barcode ha il vantaggio dei simboli alfanumerici ( poi magari lo amplieremo con altri caratteri, come le lettere minuscole dell’alfabeto ), ma presenta il problema della grandezza del disegno del codice, infatti si ha bisogno di molto più spazio orizzontale per disegnarlo rispetto agli altri.
Sono arrivato alla convinzione che un abbonamento per tutti i miei software gestionali sia il…
MerciGest è un software per la gestione del magazzino completamente gratuito. Continua a leggere→
In ufficio può capitare di doversi allontanare dal proprio posto di lavoro, ecco che allora…
In questo articolo vedremo quando è più o meno utile togliere la corrente ad un…
Dopo la pausa invernale dovuta al lavoro che devo fare per sostentarmi, eccomi di nuovo…
Vediamo come eliminare i files direttamente da Windows senza utilizzare il cestino. Continua a leggere→