From Attachment to File via Flow?

Some days ago I got a message asking me if it was possible to move from Attachments to Files in Salesforce using the #clicksnotcode tool VisualFlow and after some researches I would say no, this is not possible without code. But if you find the way, please, please, please, leave me a message so that I can update this post.

So, what is this post about? My researches and how I got that the answer is no.

First of all, the use case. As you know we cannot create Attachments in Lightning Experience, only Files are available in LEX, so anything that we want to keep should be also migrated.

But how?

  • Manually? That could be a really expensive option, and tired, to be honest.
  • Via code? Yes!! I like this option. At the end, a File is a Salesforce Object, ContentVersion , and as you can find on this blog, with a really simple piece of code you can create a new File record. Below piece adds the query to an attachment. After that, find the image with the new file and also the result of a query done in  Workbench.
List<Attachment> attList = [SELECT 
                               Body,BodyLength,Name,ParentId 
                            FROM Attachment limit 1];
Attachment att = attList.get(0);

String fileContent = att.body.toString();
ContentVersion conVer = new ContentVersion();
conVer.PathOnClient = 'MigratedFile.txt';
conVer.Title = 'MigratedFile.txt';
conVer.Description = att.Name + ' migrated';
conVer.VersionData = EncodingUtil.base64Decode(fileContent);
conVer.FirstPublishLocationId = '001B000000hYespIAC'; 
insert conVer;

Captura de pantalla 2018-06-28 a las 17.15.33

Captura de pantalla 2018-06-28 a las 17.20.22

And what about VisualFlow?

I created something really simple, 4 steps flow. But it has a welcome and a thanks screen, so actually the job is done in 2 steps.

Captura de pantalla 2018-06-28 a las 17.30.46

First one is Record Lookup where I retrieve the single attachment that I have in my organization. Please, keep in mind that if you have a list of Attachments, and use a Record Lookup, it will return a single record, but if your idea is to retrieve all attachments, you need to use a Fast Record Lookup step.

Captura de pantalla 2018-06-28 a las 17.31.10

This step is going to store data into the variable that I created, and all of them are similar, Text variables.

Captura de pantalla 2018-06-28 a las 17.31.48

The second step is to create the ContentVersion record, assigning the variable data that I got on the previous step.

Captura de pantalla 2018-06-28 a las 17.32.00

And that is all. Yes, so simple.

However, when I run it I got an error and this email where I can see that there is an issue on VersionData field.

Captura de pantalla 2018-06-28 a las 17.42.18

The reason is simple. Attachment Body returns a Blob that I need to convert into String in order to be able to encode and pass to the Content file.

....
String fileContent = att.body.toString();
....
conVer.VersionData = EncodingUtil.base64Decode(fileContent);
....

Is there a way to fix it? No as far as I could find. My first idea was to check what the variable was returning, adding a middle step to show the body value

Captura de pantalla 2018-06-28 a las 17.55.06

And as I expected that is not my body text

Captura de pantalla 2018-06-28 a las 17.54.46

So the next thought was to try to create a formula in flow or make any transform, something that could help me, but I couldn’t find any.

Captura de pantalla 2018-06-28 a las 17.51.16

So I think that the only way to do it is via some Apex code. We can create a class that has InvocableMethod annotation and do the transform there and call the class as it was an step, but, to be honest, why do I want to do it when I can run the whole transform from an apex class as I explained before?

At the end, I would advice to create your own ApexClass that execute the process to do the migration if you do not want to use the tool that Salesforce provides.

Good luck!!

API to Create CustomField

In the last few weeks, and for my first time, I started working with the Salesforce Tooling API. This scared me a bit because new beginnings are hard for me, but at the same time I liked the challenge.

In a similar way other Salesforce APIs help you to get records data, Tooling API is used in order to access / create metadata. But Tooling could sound weird, how can I run this one? Not difficult at all as this is also accesible via SOAP and REST API. What does it mean? You can make Tooling API calls via REST calls as long as the Object says that. For instance, ApexCodeCoverage supports Query and Get REST API calls, while with CustomField you can also do Post and Patch calls.

Let’s dig a bi. If you open Workbench and execute

/services/data/v42.0/tooling/sobjects/CustomField

you get information about this Salesforce object, so the Get REST API call works.

Captura de pantalla 2018-06-03 a las 14.22.08

But what about if I need to retrieve information about a certain CustomField? Same as you were trying to get information about a certain Account record.

Having the custom field Field1__c, I only need to look for its Id

Captura de pantalla 2018-06-03 a las 14.26.42Captura de pantalla 2018-06-03 a las 14.26.52

and use it in the get call

/services/data/v42.0/tooling/sobjects/CustomField/00Nb0000009GqvP

Getting this result

Captura de pantalla 2018-06-03 a las 14.29.51Captura de pantalla 2018-06-03 a las 14.30.08Captura de pantalla 2018-06-03 a las 14.30.18

That is really cool, but what I really need is to create a new custom field related to CO1__c custom object, and maybe I didn’t write the right words in google, but I didn’t find it anywhere so I took me few rounds till I get it.

My first try was to create a JSON body following Salesforce help:

{ 
   "DeveloperName": "CO1__c.test__c", 
   "ManageableState": "unmanaged", 
   "Metadata": { 
      "label": "test", 
      "description": "my new test field", 
      "length": "32", 
      "type": "string" 
   }, 
   "TableEnumOrId":"01Ib0000000gSh6"
}

And after running a POST call with the url:

/services/data/v42.0/tooling/sobjects/CustomField/

I got this error:

Captura de pantalla 2018-06-03 a las 14.40.51.png

So I continued testing things. Removing fields, changing values etc, till I got it with the following JSON body

{ 
   "FullName": "CO1__c.test__c", 
   "Metadata": { 
      "label": "test", 
      "description": "my new test field", 
      "required": false, 
      "externalId": false, 
      "type": "Text", 
      "length": 32 
}

Getting the result:

Captura de pantalla 2018-06-03 a las 14.45.05

And in the org the new field created

Captura de pantalla 2018-06-03 a las 14.45.22

What about if I need to do it in Apex? With a simple HTTPRequest call you can run same code I executed in workbench.

Another alternative is create your own ToolingAPI wrapper class as Andy Fawcett explains on this old entry.

And that is all for this entry, but don’t think this was my original challenge. What I was asked to do was to check if I could create a Sandbox environment via the Tooling API … keep an eye on future blogs because I will publish it if I get it 😉

Visualforce y Lightning Experience

Después de un gran parón en mi blog debido a dreamOlé y otros eventos, hoy me gustaría publicar un post muy pero que muy pequeñín sobre una funcionalidad que nos trae la Summer ’18: visualizar una página Visualforce con estilo Lightning Experience.

Lo primero de todo, comencemos con la pregunta:

¿Trabajas en Lightning Experience?

Si, tu respuesta es NO … no eres el único, ya que una servidora sigue abriendo Classic UI casi siempre, pero chicos, hay que ser valientes y movernos a LEX !!!

Una de las razones por las que sigo en Classic es porque soy de la vieja escuela, y cuando tengo que montar una nueva UI me voy a Visualforce en vez de Lightning Components. Segundo error …. es hora de perder el miedo a Lightning Components y empezar a desarrollar UI de la forma que Salesforce nos aconseja.

¿Qué pasa si mi producto tiene ya cientos de páginas Visualforce? ¿Debo migrar todo a Lightning Components?

Teniendo en cuenta que el tiempo que puedes necesitar para ello puede ser elevado, y que desgraciadamente Lightning Components no ofrece toda la funcionalidad de Visualforce, yo migraría aquello que fuera sencillo. Por otro lado, si hay que hacer una nueva UI, revisad primero si Lightning Components os sirve.

¿Qué hacemos con el resto?

Salesforce responde a nuestras súplicas, y en mi caso, casi me echo a llorar cuando vi lo sencillo que era aplicar el estilo Lightning Experience a una página existente, de forma que pasamos de esto:

Captura de pantalla 2018-05-25 a las 11.44.33

A esto:

Captura de pantalla 2018-05-25 a las 11.45.42

¿Cómo lo hemos conseguido? Fácil.

Para ello necesitamos una Visualforce, que hemos rescatado de esta entrada, donde creábamos una vista alternativa a una cuenta, junto con su listado de oportunidades.

Una vez que tenemos nuestra página Visualforce, tenemos que asegurarnos que será visible en Lightning Experience, para lo que tenemos que marcar el checkbox “Available for Lightning Experience, Lightning Communities and the mobile app”

Captura de pantalla 2018-05-25 a las 11.43.51

Con esto conseguimos visualizar la página en Lightning Experience. Es decir, sin este checkbox, aunque usemos esta página para sobre-escribir la vista de un registro de Account, y la visualicemos en Classic UI, si nos movemos a LEX, visualizaremos la página Standard de Salesforce en LEX en vez de la nuestra.

Y por último (si un último paso!!) sólo tenemos que añadir lightningStyleSheets="true" al tag <apex:page> de forma que nuestra página quedaría así:

<apex:page standardController="Account" lightningStyleSheets="true">
 <apex:form >
  <apex:pageBlock title="Vista Cuenta">
   <apex:pageBlockButtons >
    <apex:commandButton value="Edit" action="{!edit}"/>
   </apex:pageBlockButtons>

   <apex:pageBlockSection title="Campos Cuenta" columns="2">
    <apex:outputField value="{!account.name}"/>
    <apex:outputField value="{!account.site}"/>
    <apex:outputField value="{!account.type}"/>
    <apex:outputField value="{!account.accountNumber}"/>
   </apex:pageBlockSection>
  </apex:pageBlock>
 </apex:form>
 <apex:relatedList list="Opportunities" />
</apex:page>

Si quieres saber más, échale un ojo a este link.

 

BigObjects and Triggers

Some months ago I wrote an entry about BigObjects and since that moment I go lot of comments with questions and some useful information that I missed in my post and I would like to include here because sometimes, we do not read comments.

Not all SOQL statements are valid. For now, the !=, LIKE, NOT IN, EXCLUDES, and INCLUDES operators are not valid in any query.

There are already some Standard Big Objects like FieldHistoryArchive, so do not try to create one directly, and check before if it already exist.

Unfortunately SOSL is not supported by BigObjects.

But maybe the most important one was the fact that people was not able to create BigObject records from Triggers. It was a big surprise for me because documentation said that you could not create triggers related to a Big Object, but nothing about not be able to create Big Object records from triggers. So today I decided to give it a try.

If you have taken a look at my blog, the use case was to archive Code Review records so that we could end up with Code Review History records. Although it doesn’t make too much sense, create History records in a trigger, I decided to make it simple and continue with these objects.

So the first idea was to create a Trigger related to CodeReview__c:

trigger CodeReviewTrigger on CodeReview__c (after insert)
{
   List<CodeReviewHistoric__b> crhToInsert = new List<CodeReviewHistoric__b>(); 
   for (CodeReview__c cr: Trigger.new)    
   { 
      CodeReviewHistoric__b crh = new CodeReviewHistoric__b();        
      crh.CanBeMerged__c = cr.CanBeMerged__c ? 'true' : 'false';        
      crh.CodeReviewDate__c = cr.CodeReviewDate__c;         
      crh.Comments__c = cr.Comments__c;        
      crh.Employee__c = cr.Employee__c;        
      crh.Score__c = cr.Score__c;        
      crh.Story__c = cr.Story__c;        
      crhToInsert.add(crh);    
   }
   Database.insertImmediate(crhToInsert);
}

However, when I tried to create a Code Review record via the UI, I got below error

Captura de pantalla 2018-02-18 a las 15.16.26

and if I checked log, I also got this one.

Captura de pantalla 2018-02-18 a las 15.16.54

So came back to BigObjects product manager suggestion:

However a workaround could be to put the insertImmediate() call into a queueable method

But why queuable method? I think the key point is that we need a different context, a new transaction, so it doesn’t matter the way to get it, and I decided to keep things simple using a @future method in order to perform the Database.insertInmediate action. Then, this method will be called from the trigger.

But this annotation has several restrictions, like argument types. It doesn’t support a list of SObjects, but it allows a List of Ids.

So Trigger will look like this:

trigger CodeReviewTrigger on CodeReview__c (after insert)
{    
   List<Id> codeReviewIds = new List<Id>(); 
   for (CodeReview__c cr: Trigger.new)    
   {        
      codeReviewIds.add(cr.Id);    
   }
   AsyncProcess.createBigObjectRecords(codeReviewIds);
}

And @future one like this:

public with sharing class AsyncProcess
{
   @future
   public static void createBigObjectRecords(List<Id> crIds)
   {
      List<CodeReviewHistory__b> crhToInsert = new List<CodeReviewHistory__b>();
      for (CodeReview__c cr: [Select Id, 
                                     CanBeMerged__c, 
                                     CodeReviewDate__c, 
                                     Comments__c, 
                                     Employee__c, 
                                     Score__c, 
                                     Story__c 
                               From CodeReview__c 
                               Where Id In :crIds])    
      {
         CodeReviewHistory__b crh = new CodeReviewHistory__b();
         crh.CanBeMerged__c = cr.CanBeMerged__c ? 'true' : 'false';            
         crh.CodeReviewDate__c = cr.CodeReviewDate__c;             
         crh.Comments__c = cr.Comments__c;            
         crh.Employee__c = cr.Employee__c;            
         crh.Score__c = cr.Score__c;            
         crh.Story__c = cr.Story__c;            
         crhToInsert.add(crh);    
      }     
      Database.insertImmediate(crhToInsert);    
   }
}

And now it works sucessfuly

Captura de pantalla 2018-02-18 a las 16.37.46

Captura de pantalla 2018-02-18 a las 16.39.40.png

Any other options? Batch Apex, Queueable, even, you can use Async SOQL via a http call.

I’m sure that I still miss things about BigObjects but another amazing resource to check is the Salesforce MVP Alba A. Rivas blogs about this technology.

 

Se acercan más eventos …

Tengo la sensación de que últimamente sólo escribo sobre eventos, y estoy dejando un poco de lado las entradas técnicas. Tengo varios “to-do” en mente, pero un porcentaje bastante alto de mi participación en la Comunidad de Salesforce es por medio de eventos, así que ahí va otro post hablando de lo mismo…

Próximas fechas destacadas en Bilbao:

2 de Marzo

Tendremos el primer Salesforce Developer Group del año en Bilbao y llegamos pegando fuerte. Mi compañero de FinancialForce, Yoel Caises, que está haciendo un doctorado en Data Mining en la Universidad de Granada, ha estado explorando Einstein y nos contará todo lo que ha aprendido en estos últimos meses. Más información aquí.

20 de Abril

Segundo SDG de Bilbao. Si, tenemos otro evento ya anunciado, pero es que Trailhead DX está a la vuelta de la esquina (28 y 29 de Marzo) y posteriormente celebraremos un Global Gathering para acercar todo lo que se anunció en esta conferencia, a aquellos que no podemos asistir. ¿Quieres apuntarte? Utiliza este link para ese meetup.

27 de Abril

Un día muy importante en mi calendario, y no sólo porque sea el cumpleaños de mi querida hermana, sino porque celebramos dreamolé ’18 en el hotel Catalonia Barcelona Plaza.

Siempre y cuando nuestro público sea receptivo a la idea, los organizadores de dreamOlé queremos tener un evento itinerante. Comenzamos en la capital de España, Madrid, y ahora no movemos a la segunda ciudad más importante del país, Barcelona.

Para aquellos que no sepáis qué es dreamOlé, en nuestra web podéis encontrar más información, pero básicamente es 1 día dedicado a la comunidad.

A lo largo de todo el mundo, surgió la inquietud de acercar Dreamforce a aquellos que no pueden ir a una conferencia de tal magnitud en San Francisco, naciendo así los “dreamin events”. Y dreamOlé es uno más.

¿Y qué puedes encontrar allí?

  1. Keynote de apertura por parte de Holly Firestone, Director at Salesforce, Trailblazer Community and Community programs.
  2. Charlas en paralelo (inglés y español). Tanto si estás empezando como si eres un experto, seguro que encuentras una charla para ti ya que intentamos que los temas sean variados (desarrollo, administración, marketing, etc.) y para todos los niveles (old, new & hot topics) . Todavía estás a tiempo para mandar tu idea. Cerramos nuestro “call for speakers” el 1 de Febrero. Que no te de vergüenza dar un paso al frente y subir al scenario. Seguro que tienes experiencias que compartir.
  3. Stands para nuestros sponsors. Habla con empresas que ya trabajan con Salesforce ¿Quieres hacer algún negocio y comprar alguna app? Es tu sitio!! ¿Tu empresa se dedica a desarrollo pero no os vendría mal colaborar con otros usando su API y no tener que desarrollar algo que ya existe? Pregúntales!! Y quizás lo más importante es ¿estás buscando trabajo? Muchos de nuestros sponsors tienen puestos abiertos. Os daremos la oportunidad de tener pequeñas entrevistas el día del evento. Y si estás leyendo esto y piensas que tu empresa podría estar interesada en sponsorizar dreamOlé ’18, no dudes en ponerte en contacto con nosotros. Aquí puedes encontrar más información.
  4. DemoJam ¿Y qué es esto? Algunos de nuestros sponsors tendrán 3 minutos para mostrarnos su producto. Tanto si está en AppExchange cómo si no, pueden participar. Lo importante es mostrar la aplicación en vivo y en directo. Todos los asistentes de dreamOlé podremos votar por la que nos guste más, que se llevará un premio patrocinado por Salesforce AppEchange. ¿Y quien lo presenta? Contamos con Joshua de nuevo!! Muchas gracias!! ¿Todavía no te haces a la idea? Échale un ojo a la demoJam del año pasado.
  5. KeyNote de cierre por parte de Zayne, Salesforce Evangelist. ¿Te suena su cara? Normal!! Zayen presentó parte de la KeyNote de Desarrollo en San Francisco durante Dreamforce ’17 y nosotros tenemos la gran suerte de contar con ella en nuestro evento. Y no solo como speaker. Tanto Zayen como Holly estarán todo el día con nosotros así que no dudes en sentarte con ellas y aprender.
  6. After party. No te vas a quedar con hambre. Durante el evento ofreceremos desayuno y comida pero claro, una vez que terminamos, tenemos que celebrar este gran día con un picoteo, música, fotos, vamos lo que es una buena fiesta en España.

¿Todavía tienes dudas? ¿Ir ó no ir a Barcelona? Échale un ojo a nuestra web y mira las fotos de dreamOlé ’17 en Madrid. Al igual que el año pasado, contamos con un equipo que plasmará el día entero hacienda fotos y videos todo el día. Échale un ojo al video resumen.

Las entradas todavía no están a la venta, pero síguenos en Twitter y Linked-In para ser el primero en comprarlas. No te esperes al último minuto, el año pasado lo vendimos todo.

Recuerda, 27 de Abril, Hotel Catalonia Plaza, Barcelona, here we go!!

Process billions of records with Async SOQL

Christmas time is closer but I would like to deliver this last post before end of the year.

Some months ago, I wrote an entry talking about BigObjects, a feature that was General Available by Winter ’18 and via a use case, I tried to explain it. Now, I would like to follow that post with a new way to create records, Async SOQL.

Async SOQL is half GA by Winter ’18 and half still in Pilot 

The use case talked about moving Code Review custom object records, into Code Review History big objects records, and release storage of custom objects one. We want to Archive records, and Async SOQL will help us to deal with big amounts of data.

What is Async SOQL?

Basically Async SOQL allows you to run SOQL in the background so that, you will get a response after a period of time, but at the same time, helps you to deal with millions or even billions of records without hitting time outs or governor limits.

How can I execute Async SOQL?

Async SOQL is implemented as REST full API and in order to execute this SOQL in the background we need to run a post request:

Captura de pantalla 2017-11-29 a las 21.51.22

And provide a body in JSON format in order to make the call. Find bellow a really easy example that helps you to create Vendor__c custom object records based on Accounts.

Captura de pantalla 2017-12-19 a las 9.40.12What can we highlight?

query: allows you to define a SOQL. On our case, the object I’m going to read, Account and the field I want to recover, Name.

operation: help us to define what we want to do, insert or upsert (please check big objects entry to understand Primary Key and upsert, as it works in the same way)

Basically that is the main difference between simple SOQL and Async SOQL. With this new feature we can read and create or update records in one go.

targetobject: object we want to use to create new records. In our case, Vendor__c.

Then, we need to specify from where we want to get record field values and where we want to store this info. For that we have 2 keys in this JSON code.

targetFieldMapping: allows you to define source field and target fields

and

targetValueMap: allows you to map a target field with a literal value, for instance, we want all records have Spain as Country__c field value.

How is the response?

When we do the post call, we get a similar response:

Captura de pantalla 2017-11-29 a las 22.01.12

It is also in JSON format and basically it provides similar information that you passed in the post call. Just highlight 3 keys:

jobId: remember this is an asynchronous call so there is an Id related to the background job. You can also use it in the post call via the global variable $Job_Id as part of key value on targetValueMap.

status: helps you to know where is the job. Moving from New to Running, Complete, Failed etc.

message: before executing the call, the code is analyzed. If it realizes about a possible issue, it doesn’t start the call and provides an error message in that field. For instance, below message. My VendorName__c field size was too short to store all Account Names.

Captura de pantalla 2017-11-29 a las 22.11.03.png

How can I stop the execution?

Async SOQL doesn’t provide a UI in Salesforce like other background jobs like Batch Apex or Queueable. But we can make an http delete call passing the jobId as part of the url.

Captura de pantalla 2017-11-29 a las 22.22.02

How can I check the progress?

Similar as before, as we do not have UI, we need to look for another way in order to get this information. For that, we have 2 options:

1º – Make a get post call: Similar to the cancel action, if we pass the JobId as part of the url, and do a get call, the response shows you information abut the background execution that is running in the system.

Captura de pantalla 2017-11-29 a las 22.32.33

2º – Make a SOQL against BatckgroundOperation object: This is a new object where we can see extra information about the job execution.

Captura de pantalla 2017-11-29 a las 22.32.42

But this is not the only new object that we can get in the system. We also have BackgroundOperationResult that will help you to identify any issue during the execution if the result is not the expected one. For instance. Bellow image shows an issue related to a field that is required but the source value is empty. In that case, a new error is logged on this table, but the execution doesn’t stop, it continues till the end.

Just keep in mind that this information would be removed after 7 days.

Captura de pantalla 2017-11-29 a las 22.32.55

And what about Archiving?

Yes, you are right. We promised to show you how to archive Code Review records but tried to explain the whole functionality with a really simple use case. Now it’s time to move to Code Review History use case.

As I mentioned before, we would like to create Code Review History records reading Code Review records. Similar as before we will do a post call but the body would be like this one:

Captura de pantalla 2017-11-29 a las 22.51.40

On BigObjects post, the object was called Test1CodeReviewHistory__b instead of CodeReviewHistory__b

And … that’s all. Simple, isn’t it?

Can I integrate this functionality into Apex?

Yes, of course, at the end we are just making http calls, so we only need to set the proper url, add it on my remote settings and create a string in JSON format for the body.

Captura de pantalla 2017-11-29 a las 22.42.57

Summary

Finally I would like to sum up some key concepts we have talked about.

  1. Async SOQL allows you to run SOQL in the background
  2. It takes some times but allows you to process millions or even billions of records
  3. You do not need to worry about governor or time out limitations
  4. It is implemented as REST full API
  5. You can make as many calls as you want per day but just a single one at a time
  6. You can read and create records in one go. Delete is out of scope
  7. This feature is part GA and part still in Pilot:
    1. Read Standard or Custom objects and create Standard, Custom or Big Objects is in Pilot
    2. Read Big Objects and create Standard, Custom or Big Objects is GA

Captura de pantalla 2017-11-29 a las 22.43.44

Salesforce Elevate – Bilbao ’17

During Dreamforce ’17 Erika Kuhl, Holly Firestone and their team showed us how they are working really hard to get more content ready for our Developer and User Groups, and some other amazing ideas that can help us to get more attendees, like Global gathering events.

But in the meantime their ideas take effect, I had to think about something to do it now, as every single day, the number of guests at North Spain Developer User Group, is lower. And to run a second Elevate in Bilbao didn’t sound like a bad idea. And that’s what I did, prepare a 1 day event to talk about Salesforce.

What did I do?

First thing to keep in mind, the main objective is to get audience that could be interested to continue attending SDG talks … and where can I get this?

Facultad IngenieriaUniversity could be a good option. There are lot of students keen to know more about new technologies, solutions, and furthermore, that could be a good scenario to promote the open door that Salesforce can give them in their job career. And that is what I did, talked with the University of Deusto in order to run the event there.

Secondly, I needed some sponsors that could help me to support the event.

Salesforce Iberia, helped me with catering and Jon Ibáñez came to the event in order to talk about Salesforce platform. I really appreciated this introduction talk as it was really useful, even for me, that I’m on this world since almost 10 years ago.

 Jon1

NTS with Carlos Polo and Esteban Ugarte, was really helpful with catering expenses too, and also running a couple of sessions, like the one that Gorka run about Salesforce and Chatbots. Looking forward to know more about this topic, that allows you to create chats able to answer questions.

But I also needed some more help with sessions. FinancialForce was also an amazing help. Miguel Moro and Agustín Jimenez came from our Granada office to talk about the company itself, and also run a really good talk about Separation of Concerns (SoC) #qualitycode guide, that can help us to enhance our code and make it more readable and useful via the FinancialForce open source ApexLib.

Also, I wanted to provide a success case to the audience. Not only explain all benefit that Salesforce could bring to us. I wanted to show a real use case and I got it closer than expected. University of Deusto is a Salesforce customer too, and we had 2 good examples. First of all how they use Salesforce as a solution provider to the needs that the University can have. And secondly how they use and configure Salesforce without technical knowledge, with just #clicksnotcode.

Finally, the main goal of the event, promote other events, but we needed to start talking about Salesforce Community, our #ohana spirit , how we help each others, that we need some others to continue with this job, and how events like SDG or dreamin events could help. And guess what? As part of dreamOlé organizers, obviously I talked about this event that will be run in Barcelona next 27th of April.

 After a nice lunch…

We moved to the afternoon sessions, Chatbots one run by NTS and Process Automation with and without Code that I also ran.

And finally, time to dirty our hands working with Salesforce via Trailhead. Thanks Christie and your team to help me with this section and sending to me such nice stickers!!

What have I learnt on this event?

2 years ago I run a similar event but Trailhead just appeared few months ago and sessions we run were workshops to learn how to starts. Because of the low level of the content, some attendees complained. They were expecting something more than how to create an App with #clicksnotcode.

That made me think to prepare this Elevate with sessions with higher level, and Trailhead allowed newbies to start from scratch.

However, this year feedback was that it would be useful to have a quick overview of the platform, a demo or something similar as a first session just for starters, and then move to other sessions.

So keep in mind my feedback if you are thinking on running something similar for your group.

If you want to take a look at slides, find them here as well as some others. And don’t forget to join us at North Spain Developer User Group.  Next talks about Data Mining and Einstein, Javascript and Salesforce and working on a Salesforce DX workshop.

Thanks to everyone that helped me to make this Elevate event real