Categories: ProgrammazioneVC/C++

Cambi Valutari Aggiornati da una Pagina Web

Qualche giorno fa ho rilasciato un piccolo strumento software, WinValue 2012, che permette di fare le conversioni delle valute internazionali. Questo semplice programma nasce dallo strumento interno al nostro software gestionale Vikings 2012 Business. I calcoli da fare per la conversione sono molto semplici, infatti in una tabella di un database memorizzeremo i cambi riferiti all’euro, poi basta solo rapportare i valori a quest’ultima valuta.

WinValue 2012 – Strumento software per la conversione delle valute

Il cuore del programma è il piccolo parser che occorre scrivere per prelevare i dati valutari da una pagina web. Nel mio caso ho utilizzato il sito della Banca d’Italia e per questo ho scritto un parser in C++ su MFC per prelevare i dati da una pagina web ( http://uif.bancaditalia.it/UICFEWebroot/cambiUltimiDisp_fw.do?type=14&lingua=it ) che ha una struttura tabellare. Ecco il mio codice racchiuso in una classe parser che raccoglie i valori in vari array.

// File InternetCambi.h
#pragma once

#include <afxtempl.h>
#include <afxinet.h>

class CInternetCambi
{
public:
   CInternetCambi();
   ~CInternetCambi();
protected:
   CInternetSession m_session;
   CString m_strUrl;
   CStringArray m_arrPaese;
   CStringArray m_arrValuta;
   CStringArray m_arrSimbolo;
   CArray m_arrValore;
   BOOL OpenAndParse(void);
   BOOL GetOneValue(CStdioFile* pFile, CString strFirst);
public:
   BOOL SetUrl(CString strUrl);
   CString GetPaese(int index);
   CString GetValuta(int index);
   CString GetSimbolo(int index);
   float GetValore(int index);
   int GetValuteCount();
};

// File InternetCambi.cpp

#include "StdAfx.h"
#include "InternetCambi.h"

CInternetCambi::CInternetCambi()
{
   m_strUrl.Empty();
}

CInternetCambi::~CInternetCambi()
{
}

BOOL CInternetCambi::SetUrl(CString strUrl)
{
   m_strUrl = strUrl;
   return OpenAndParse();
}

BOOL CInternetCambi::GetOneValue(CStdioFile* pFile,
      CString strFirst)
{
   CString strPaese, strValuta, strSimbolo, strValore;

   strPaese = strFirst.Mid(16, strFirst.GetLength() - 21);

   if (!pFile->ReadString(strFirst))
      return FALSE;
   strFirst.Trim();
   strValuta = strFirst.Mid(16, strFirst.GetLength() - 21);

   if (!pFile->ReadString(strFirst))
      return FALSE;
   strFirst.Trim();
   strSimbolo = strFirst.Mid(17, strFirst.GetLength() - 22);

   if (!pFile->ReadString(strFirst))
      return FALSE;

   if (!pFile->ReadString(strFirst))
      return FALSE;
   strFirst.Trim();
   strValore = strFirst.Mid(16, strFirst.GetLength() - 21);

   if (!pFile->ReadString(strFirst))
      return FALSE;
   if (!pFile->ReadString(strFirst))
      return FALSE;
   if (!pFile->ReadString(strFirst))
      return FALSE;
   if (!pFile->ReadString(strFirst))
      return FALSE;

   m_arrPaese.Add(strPaese);
   m_arrValuta.Add(strValuta);
   m_arrSimbolo.Add(strSimbolo);
   m_arrValore.Add((float)_wtof(strValore));

   return TRUE;
}

BOOL CInternetCambi::OpenAndParse()
{
   if (m_strUrl.IsEmpty())
      return FALSE;

   DWORD_PTR dwFlags = 0;
   if (!::InternetGetConnectedState(&dwFlags, 0))
      return FALSE;

   CHttpFile* pFile = NULL;

   TRY
   {
      pFile = (CHttpFile*)m_session.OpenURL(m_strUrl, 1,
         INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_RELOAD);
   }
   CATCH (CInternetException, e)
   {
      e->ReportError();
      m_session.Close();
      return FALSE;
   }
   END_CATCH

   if (pFile == NULL)
   {
      pFile->Close();
      m_session.Close();
      delete pFile;
      return FALSE;
   }

   // Dato che siamo in ambiente unicode e il trasferimento
   // gestisce solo char ecco che faccio la conversione

   TCHAR szPath[MAX_PATH];
   ::GetTempPath(MAX_PATH, szPath);
   CString strPath(szPath);
   strPath += _T("\\tempvalute.txt");

   CStdioFile file;

   if (!file.Open(strPath, CFile::modeCreate|
           CFile::modeWrite|CFile::typeBinary))
      return FALSE;

   CHAR buf[512];
   int k;
   while (k = pFile->Read(buf, 512))
      file.Write(buf, k);

   pFile->Close();
   file.Close();
   m_session.Close();
   delete pFile;

   if (!file.Open(strPath, CFile::modeRead))
      return FALSE;

   CString strRow, buf1, buf2;
   bool bInside = false;
   while (file.ReadString(strRow))
   {
      strRow.Trim();

      buf1 = strRow.Left(10);
      buf2 = strRow.Mid(16, strRow.GetLength() - 21);

      // Trovo la prima sequenza
      if (!bInside && buf1 == _T("<td width=") &&
               buf2 == _T("AFGHANISTAN"))
 bInside = true;
      if (bInside && buf1 == _T("<td width=") &&
               buf2 == _T("ZIMBABWE"))
      {
 if (!GetOneValue(&file, strRow))
    return FALSE;
 bInside = false;
      }

      if (bInside)
      {
 if (!GetOneValue(&file, strRow))
    return FALSE;
      }
   }

   file.Close();
   ::DeleteFile(strPath);

   return TRUE;
}

CString CInternetCambi::GetPaese(int index)
{
   return m_arrPaese.GetAt(index);
}

CString CInternetCambi::GetValuta(int index)
{
   return m_arrValuta.GetAt(index);
}

CString CInternetCambi::GetSimbolo(int index)
{
   return m_arrSimbolo.GetAt(index);
}

float CInternetCambi::GetValore(int index)
{
   return m_arrValore.GetAt(index);
}

int CInternetCambi::GetValuteCount()
{
   return (int)m_arrPaese.GetCount();
}

Questo è il codice della classe “CInternetCambi“, di certo è possibile migliorarla, ma il suo lavoro lo compie discretamente, inoltre con molta semplicità è possibile adattarla ad altri linguaggi. Spero che vi possa essere di utilità per lo sviluppo dei vostri software. Come sempre per approfondimenti o altre spiegazioni vi invito ad iscrivervi al forum sulla programmazione.

Share
Giampaolo Rossi

Sviluppatore di software gestionale da oltre 28 anni.

Published by
Giampaolo Rossi

Recent Posts

Un Abbonamento per Tutti i Software

Sono arrivato alla convinzione che un abbonamento per tutti i miei software gestionali sia il…

11 mesi ago

Software di Magazzino Gratuito

MerciGest è un software per la gestione del magazzino completamente gratuito. Continua a leggere→

11 mesi ago

Mettere il PC in Lock Screen

In ufficio può capitare di doversi allontanare dal proprio posto di lavoro, ecco che allora…

3 anni ago

Fare il reset togliendo la corrente

In questo articolo vedremo quando è più o meno utile togliere la corrente ad un…

3 anni ago

Prossimi Aggiornamenti Software

Dopo la pausa invernale dovuta al lavoro che devo fare per sostentarmi, eccomi di nuovo…

3 anni ago

Come Eliminare i Files in Windows

Vediamo come eliminare i files direttamente da Windows senza utilizzare il cestino. Continua a leggere→

3 anni ago