miércoles, 1 de abril de 2015

Como enviar un CSV de VB6 por .NET y de .NET a Google SpreadSheets

La tarea no es fácil, vamos a generar un CSV en VB6 y de ahí consumir una componente .NET y de ahí pasar a GoogleSpreadSheets. Esto es porque investigando, pasar desde VB6 a GoogleSpreadSheets directamente es medio complicado, por lo que usaremos .NET como "puente".

Usaremos:

  • Visual Studio 2013
  • .Net Framework 2.0.
  • Visual Basic 6

  • Configuración en la cuenta Google


    En la cuenta de correo que usará Google Spreadsheets:
  • Crear un proyecto en: https://console.developers.google.com Y activar la API Drive API.
  • Activar aplicaciones no seguras: https://www.google.com/settings/security/lesssecureapps, esto porque no usaremos OAuth 2.0, sino un acceso directo del código con el correo/clave.

  • Codificar la componente .Net


    Instala Google_Data_API_Setup_*.msi, en mi caso bajé Google_Data_API_Setup_2.2.0.0.msi.
    Las dll quedarán en por defecto en:

    C:\Program Files (x86)\Google\Google Data API SDK\Redist\

    Fuente: https://developers.google.com/google-apps/spreadsheets/.

    Usaremos .Net Framework 2.0, así que en Visual Studio 2013 crear un proyecto tipo Librería de Clases usando esta versión del Framework.

    Referencia a las DLL:

  • Google.GData.Client
  • Google.GData.Documents
  • Google.GData.Extension
  • Google.GData.Spreadsheets

  • Como dije, sácalas de: C:\Program Files (x86)\Google\Google Data API SDK\Redist\

    Configura el proyecto

    En el archivo AssemblyInfo.cs configura:
    [assembly: ClassInterface(ClassInterfaceType.None)] 
    [assembly: AssemblyKeyFileAttribute("C:\\TFS\Google.snk")]  // C#
    [assembly: Guid("837f7063-8219-4f83-abe5-aa4240c7ac4e")]    //en c# automático
    

    En las propiedades del proyecto:

  • Build: Registrar la interoperabilidad COM
  • Aplicación -> Información del ensamblado -> Crear ensamblado visible a travéz de COM


  • Crea una interfaz (para este ejemplo es útil solo si estás consumiendo desde VB6):
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using System.Text;
    
    namespace GoogleSpread
    {
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
        public interface IFunciones
        {
            
            int SendCVSToGoogle(string ruta, string file);        
        }    
    }
    

    Crea la clase Funciones:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    using Google.GData.Spreadsheets;
    using Google.GData.Client;
    using Google.GData.Documents;
    using System.Configuration;
    using Google.GData.Client.ResumableUpload;
    
    namespace GoogleSpread
    {
    
        [ComSourceInterfaces("GoogleSpread.IFunciones")]
        public class Funciones : IFunciones
        {
    
            public Funciones()
            {
            }
    
            public int SendCVSToGoogle(string ruta, string archivoCVS)
            {
                try
                {
                    //logging...
    
                    DocumentsService service = new DocumentsService("MyDocumentsListIntegration-v1");              
    
                    string user = ConfigurationManager.AppSettings["correo"];
                    string pass = ConfigurationManager.AppSettings["pass"];
                    service.setUserCredentials(user, pass);
    
                    if (user == null || user == String.Empty || pass == null || pass == String.Empty)
                    {
                        throw new Exception("Usuario o clave incorrecta");
                    }
    
                    //logging hasta aquí ok...
    
                    Authenticator authenticator = new ClientLoginAuthenticator("TestApi", Google.GData.Client.ServiceNames.Documents, service.Credentials);
    
                    // Instantiate a DocumentEntry object to be inserted.
                    DocumentEntry entry = new DocumentEntry();
    
                    // Set the document title
                    entry.Title.Text = archivoCVS;
                    entry.IsSpreadsheet = true;
    
                    string rutaFull = ruta + "\\" + archivoCVS;
                    if (!File.Exists(rutaFull))
                        throw new Exception("Archivo ["+ rutaFull +"] no existe.");
    
                    entry.MediaSource = new MediaFileSource(rutaFull, "text/csv");
    
                    Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
                    AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
                    link.Rel = ResumableUploader.CreateMediaRelation;
                    entry.Links.Add(link);
    
                    entry.Service = service;
    
                    ResumableUploader uploader = new ResumableUploader();
    
                    //logging archivo se subirá...
    
                    // Set the handlers for the completion and progress events
                    uploader.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(OnDone);
                    uploader.AsyncOperationProgress += new AsyncOperationProgressEventHandler(OnProgress);                
    
                    // Start the upload process
                    uploader.InsertAsync(authenticator, entry, new object());
    
                    
                    return 1;
                }
                catch (Exception ex)
                {
                    //logging error
                    return -1;
                }
            }
    
            static void OnDone(object sender, AsyncOperationCompletedEventArgs e)
            {            
                DocumentEntry entry = e.Entry as DocumentEntry;
                //logging subido ok
            }
    
            static void OnProgress(object sender, AsyncOperationProgressEventArgs e)
            {
                int percentage = e.ProgressPercentage;
                //logging subido un tanto %
            }
        }
    }
    

    Crea un proyecto Test, por ejemplo un winForm con un botón.
    Agrega un archivo de configuración App.config con el correo gmail y la clave:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
       <appSettings>
            <add key="correo" value="correo@gmail.com"/>
            <add key="pass" value="clave"/>
        </appSettings>
    </configuration>
    

    Agrega el código para que hacer clic sobre el botón invoque a la componente .Net y testearla más facilmente. Recuerde referenciar primero el proyecto:

    private void button1_Click(object sender, EventArgs e)
    {
        FuncionesGoogle f = new FuncionesGoogle();
        f.SendCVSToGoogle("c:\\test", textbox2.text);
    }
    

    Prueba la componente, ejecutando el proyecto Test:

    Revisa el Log, si lo implementaste, si se guardó que se subió ok, ve a ver a http://spreadsheet.google.com y ve si se subió:

    Si abres el archivo de prueba se verá el contenido:


    Llamado desde VB6


    NOTA: Asumo que es otro PC.

    Crea una carpeta con permiso de escritura, por ejemplo C:\temp.

    Adentro deja los archivos:

  • GoogleSpread.dll y GoogleSpread.tlb
  • Además las DLL:
    Newtonsoft.Json.dll, Google.GData.AccessControl.dll, Google.GData.Client.dll, Google.GData.Extensions.dll, Google.GData.Spreadsheets.dll, Google.GData.Documents.dll.
    Nota: Estas 6 dll se obtienen al instalar Google_Data_API_Setup_2.2.0.0.msi obtenido de: https://code.google.com/p/google-gdata/downloads/list y que por defecto quedan en: C:\Program Files (x86)\Google\Google Data API SDK\Redist.

  • Además se debe copiar el archivo .config generado que luego lo configuraremos.

  • Referencia al tlb

    Referencia al archivo tlb:


    Seleccionar el archivo .tlb y luego presionar Aceptar.

    Llamar a la función de .Net entregandole una carpeta y un archivo csv:

    Set objNET = New GoogleSpread.FuncionesGoogle
    objNET.SendCVSToGoogle "C:\", "test.csv"
    

    Genera el .exe de salida, llamalo "testvb.exe" y dejalo en C:\temp.

    En la carpeta C:\temp entonces tenemos las 6 dll, el assembly .dll y el .tlb, el archivo tesvb.exe y el .config (con la configuración del correo) que lo debes llamar test.exe.config para que el assembly .Net lo lea correctamente.

    Ahora ejecuta el testvb.exe y cruza los dedos.

    Bueno, espero les sirva.