#ActCRM and Attachment Files Anomalies

Q#ActCRM and Attachment Files AnomaliesOne of the great things with Act! is the ability to attach files to any entity like a Contact, Company or Opportunity etc. We received a database recently from client that they wanted cleansed, upgraded and re-designed. As this dB was quite an old system that had “been through the wars” and several upgrades over the years (I think it started life as an Act! 2000 dB!) there was a fair amount of cleansing to do for us within the tech team.

dB cleansing is usually not only a complex task but also time intensive where we run a dB through various internal tools and scripts developed by us over the years. One region within most Act! dBs that requires our intense gaze is upon the Activities and then the Attachments as these sections touch so many areas with an Act! dB.

One interesting thing about Act! attachments is that when you delete a Contact, the attached files within the dB are not physically removed from the system. Attached files reside in the Attachments folder of the supplemental folders, e.g. if your dB is called Act2014Demo at the location of the ADF and ALF files you will find a folder called .\ACT2014Demo-database files and within that a folder named Attachments.

Supplemental_folders

Act! supplemental folders

It is generally accepted as a rule of thumb to carry out system purging of cleared activities etc on a fairly regular basis to reduce lock-ups in the dB and negative impacts on overall dB performance, unfortunately there is no native facility to remove unattached or orphaned files from the Attachments folder. Having too many orphaned files not only is a waste of physical space on your hard drive, but can also slow Act! down since the Indexing server within Act! that allows you to perform Universal Searches will list and index the contents of these orphaned files as well.

The real problem comes in trying to work out which files are correctly attached and which are not so the following simple script shows an example of a SQL statement that lists all the files that are currently not attached to a record in Act! and so can be safely removed.

declare @files table (ID INT IDENTITY, Filename varchar(250))
insert into @files execute master.dbo.xp_cmdshell 'DIR "C:\Users\Public\Documents\ACT\ACT Data\Databases\ACT2014Demo-database files\Attachments\" /a /b'
select  F.Filename[OrphanFiles], (select COUNT(F.filename) from @files[F] where F.Filename not in (select DISPLAYNAME from TBL_ATTACHMENT))[OrphanCount]
from @files[F]
where F.Filename not in (select DISPLAYNAME from TBL_ATTACHMENT)

What’s interesting here is that you can ask SQL to run a cmd line utility to list the contents of a folder. There are many DBAs that would balk at the idea of leaving this security gap wide open, however since we are working in the “lab” this is something that we do fairly routinely. If this ability has been turned off, then your only option then is to create a custom CLR for your SQL instance which is quite a bit more involved.

What we usually do with this SQL statement is embed it within a Powershell script with literates through the file list and deletes each file. The result is an Act! dB with a nice new hair-cut.

SQL Server Act7 Instance stuck in Starting Status

Well it’s been absolutely ages since I’ve made a post here o my blog. Quite a bit has happened in my personal and professional life since last year (my god it’s been that long!), the most important of all is that my daughter, Anoushka, was born to my wife and I and has brought so much joy to us!

This is going to be a very short post as I get back into the swing of blogging and hopefully someone might find it helpful.

I had a failed driver update for my Logitech mouse today which seemed to have killed my machine somehow. After reverting back to an earlier Restore Point (I love you Windows 8), I found that my SQL Server Act7 instance was hung on the status “Starting”, even after a reboot.

I knew I could use the cmd line command taskkill /f    to kill a process, but it needed a PID for the process. This was the bit that stumped me; how do I find the PID for a service? After a short Google session the answer came to use the sc queryex command.

So by stringing the sc queryex to a taskkill and then net start I managed to get my Act! Instance back up and running…Hurrah!

N.B remember to do this in an elevated permissions Command Prompt session!

sc queryex mssql$act7

[note down PID]

taskkill /f /pid [pid number]

net start mssql$act7

 

An Automated Weekly History Report Email for #ActCRM Using PowerShell

Windows_PowerShell_icon

I just want to apologise firstly that I haven’t been updating my blog for a little while and this could be my first post this month, but I’ve been in hospital for a little while and then on medication which has left me a little…incapacitated!

Today’s post brings in a couple of technologies and techniques together to produce an email that contains  a simple table showing the Histories created by all Users during the past week. This is actually a very simplified request that we received a little while ago from a client who was going away on holiday for a couple of weeks but still wanted to keep a tab on how their team were performing.

We’re going to use Microsoft’s PowerShell to run a SQL statement against the Act! SQL instance and then use a SMTP connection to the internal SMTP server (Exchange Server in our client’s case) to them email it out on a schedule set by nothing more exciting than the Windows Scheduler!

Now there are add-ons that will do this in a much more WYSIWYG and point-‘n’-click manner, but my view on this is; where’s the fun in that and isn’t it cheaper for the client to use the native skills of their Act! Consultant and existing free technology already present within their architecture?

Below is the script for doing this, I’ve added some comments to explain some of the parts and have tried to segment the scripts into blocks. In the current state, the script would need to be run on the server hosting the Act! dB and the scheduler to be running logged in as either a local server administrator or as a Domain administrator since it uses that to log into the SQL instance.

One word of caution though, if you’re not too comfortable with PowerShell or SQL, I would recommend that you don’t try this on your own and try to liaise with someone who is more comfortable with the technologies before using it on a production dB.

History_Summary_via_PowerShell_and_SQL

I’ve noticed that the image is a little small so here is the script itself that you could copy and paste if you’re feeling especially lazy!

clear #clears the screen of any other commands etc.
#-----------This is the PS connector to the native SQLCMD of SQL Server
if((Get-PSSnapin -Name sqlserverprovidersnapin100 -ErrorAction SilentlyContinue) -eq $null){
add-PSSnapin sqlserverprovidersnapin100
add-PSSnapin sqlservercmdletsnapin100
}
#--------------------------------------------------------------------------------------------

$dbInstance = ".\act7" #The machine hosting the Act! dB SQL Instance
$actDb = "Act2013Demo" #The Act! dB we want to report on

#----------------SQL Statement----------------------------------------------------------------
$myExp = invoke-Sqlcmd -ServerInstance $dbInstance -Database $actDb -Query "
            SELECT     
                    Count(TBL_HISTORY.HISTORYID)[Count], 
                    TBL_HISTORYTYPE.NAME AS [History Type], 
                    TBL_USER.USERLOGIN AS [User]
                FROM         
                    TBL_HISTORY INNER JOIN
                    TBL_HISTORYTYPE ON TBL_HISTORY.HISTORYTYPEID = TBL_HISTORYTYPE.HISTORYTYPEID INNER JOIN
                    TBL_USER ON TBL_HISTORY.CREATEUSERID = TBL_USER.USERID
                WHERE
                    TBL_HISTORY.CREATEDATE >= DATEADD(WW,DateDiff(WW,0,GetDate())-1,0)
                AND
                    TBL_HISTORY.CREATEDATE <= DATEADD(WW,DateDiff(WW,0,GetDate()),0)            
                GROUP BY
                    TBL_HISTORYTYPE.NAME, TBL_USER.USERLOGIN
            " | Select-Object Count, 'History Type', User
#-----------------------------------------------------------------------------------------------
#---------------Send out Email------------------------------------------------------------------
$emailFrom = 'actAdmin@caldere.com'
$emailTo = 'SalesManager@caldere.com'
$subject = "History Activity Report for week: {0}" -f((Get-Date -UFormat %V)-1)
Send-MailMessage -SmtpServer 'MyMailServer' -From $emailFrom -To $emailTo -Subject $subject -Body $myExp -BodyAsHtml
#------------------------------------------------------------------------------------------------

I’d be genuinely interested to read any comments anyone would like to make on this or if they can find ways to improve this. The original script created for the client was a little more complicated to include CSS styling and further SQL queries specific to their request.

Google Cloud Print

cloud_print_splash

Google Cloud Print

Like an innocent, fluttering moth drawn unerringly and powerfully towards the bright light of a night-light, I just can not resist cool tech and gadgets! Google usually always come out with some really exciting stuff in their labs, things we all very rapidly take for granted after a while or think “why hasn’t someone already done this?”.

So is the case with this little project which has the all-familiar Beta label; Google Cloud Print. It’s a very simple concept and one that all of us must have thought about at last once. I’ve got something on a smart phone or slate/tablet, or I’m logged into a machine away from my home or office printer and I’d love to print this xyz off…but I can’t. I’ll have to connect my device to my machine or network or printer or copy the file over to my Google drive or Dropbox account and then remote onto my machine and print it off etc etc etc.

Well Google Cloud Print does this for us. Simply we associate a desktop that has Google Chrome installed on it (and is on and connected to the net obviously!) that has a connected printer to our Google account and then we can simply print directly to that printer wherever we are! It’s simplicity and hind-sight level of obviousness was definitely a face-palm moment for me.

How-To Configure Your Printer(s)

I’ll base this on the presumption that you don’t have one of the few “Cloud Print” enabled printers but a standard windows printer.

The first thing we need to do is enable Google Cloud Print from within the preferences in Chrome:

  • Click on the Settings button in chrome at the top right hand corner of Chrome: ChromeSettings
  • Click on “Show advanced settings…” at the bottom, then scroll to the end of the page:  GoogleCloudPrint_AddPrinters
  • Click on the “Add printers” button. If you are already signed into your Google account within Chrome, you’ll see a page like this: PrinterConfirmation
  • Click on the “Add printers” again. After a small pause which will give enough time for your Google account to add the printers (maybe 5 seconds), you can then click on the link to manage your printers.myCloudPrinters
  • We can see form the above image that we can choose to share our printers with other Gmail accounts, and it’s just as simple as it’s been so far!

So that’s the printers set-up so that we can print to them, but that does leave the question begging of “how do I actually print to my cloud printers?”. Well once again Google show themselves once again to be the masters of elegant and simplistic solution design. If your printing from any Google Docs app or Chrome you can simply choose from the print menu to use Google Cloud Print by changing the destination printer:

PrintDestination

If you are not printing from a Google App or from a page in Chrome you can simply installing either an Android or Windows (or even iOS or OS X) application onto your device from this list of currently available Apps: http://www.google.com/cloudprint/learn/apps.html

One of the things that really struck me most, apart from the overall coolness of it all, was the deep thought into the overall design of the process and the solution itself. One of the most dreary things with owning a PC is the sheer drudgery of installing and updating device drivers. Google have designed their cloud printing solution to not only be simple but also engaging. As a developer this is something that has really struck me about the majority of Google’s solutions is the sheer excellence in their approach to software engineering. Good software solutions are not only about providing the end-user with power and flexibility, but ultimately they should be intuitive and simple for the end-user and should never be a source of frustration! Fantastic work Google team!

Sudden Realisation!

Bruce-Lee: A goal is not always meant to be reached, it often serves simply as something to aim at.This is a bit of a personal-life blog entry and not one of my more usual tech/work related posts. Whilst I was at Perfecting ACT! this year I had the privilege of talking to and drinking with some of my great heroes from the ACT! and CRM world. During one of the conversations I was asked how I got into development, this simple conversation starter led me to a point where I recounted a part of my long journey, which is still largely unfinished, and I thought I would share here.

My background is in Biochemistry and Molecular Biology and just before I left academia and research I was working in a research lab on mitochondrial genetics. I won’t go into the story whereby I abandoned research and went into a field I knew nothing about; namely IT, except to say that to me at the time it felt that maybe this time I had over-stretched myself by over estimating my abilities to learn new skills!

During this period of learning, I discovered an interest in development and coding so proceeded towards learning HTML and Javascript (including a failed attempt to self-learn Java). I remember late one night trawling through the internet trying desperately to find a very specific kind of tool to carry out a particular task, I kept coming across the roadblock of very expensive utilities or shareware tools that I could not afford. At the time I rather whimsically thought of a future “me” that would be an experienced developer who would simply develop a tool to fulfil the task at hand. This little daydream became, at the time, all-consuming and not only drove me further in my learning, but also tormented my confused mind with, what seemed at the time, an unachievable dream.

Many years have passed and such thoughts were forgotten as I got on with my life in IT and continued study in development, till one day I was working with one of junior members in the tech team on a project of migrating a badly designed and implemented ACT! solution to a new model.

The client had been managed by another consultancy who had made some peculiar decisions which were causing major issues downstream post-implementation. Basically the client had 7 separate dBs, each had roughly 20 remote users who would synch at set times over a 24 hour schedule. The problem was that the server hosting the master had a very poor internet connection and the remote users were all working from a satellite office and synch was very unstable, failing many times.

The obvious fix to this was to migrate all 7 dBs onto a local server at the satellite office and use the scheduler to carry out synch thereby reducing the multiple points of error. This simple task was further complicated by each dB having, in some cases, in excess of 60 child dBs that had failed and so new RDBs had been re-cut but they had not removed the old RDB from the manifest. *sigh*. So we would have to manually clean up the whole system and deleted old RDBs.

Both of us were quite irritated by the time it would take to do this and my trainee/junior like a good ACC started manually disabling and then deleting RDBs from each manifest. I decided the quickest and most efficient approach would be to simply create a utility that would do this and within half an hour I had a a working (albeit ugly) tool that went into each dB and disabled and then deleted RDBs from the manifest one by one based on the last date of successful synch. If it was greater than 6 months it would remove them.
The task was completed in a very short period of time and we were ready to continue with the rest of the project. My junior remarked to me that it was lucky that I was a dev since it was like having a Genie in a Bottle!

For some reason this suddenly sparked from the darkest recesses of my brain memories of those tortured nights stooped over a cheap desktop with a copy of Visual Studio Learning Edition feeling frustrated, tired and with an over-riding sense of defeat, idly dreaming of a better time when I could code confidently but never expecting to achieve this goal.
It then suddenly hit me like a brick. I was actually living my dream! I had and continued to do the one thing that used to motivate me to not give up at my darkest times! I must admit that afterwards in the privacy of my room I did feel a little emotional since I had achieved for myself something that truly seemed impossible and I was doing these kind of things almost on a daily basis without even thinking about it.

The reason I wanted to share this out publicly was not to trumpet my own horn, but to give others an example of how not losing faith in ourselves and our dreams, but focusing on our daily hurdles/challenges and not overwhelming our minds with what seem like impossible goals, we slowly and gradually without much fuss or theatre, find ourselves at the summit wondering how we got there.

My hope is that maybe someone who is beginning the long, lonely and painful journey towards being a developer might read this and derive some hope and confidence that the dream is achievable.

#PerfectingACT! 2013 with #Swiftpage

new act! logo

The newly revealed act! logo by Siwftpage

Well, PA 2013 is over and I’m back in the UK, comfortably sat in my “dev hole” (as wifey describes it) and though I am completely spent from 6 days of little or no sleep, I haven’t felt this energised for years! Swiftpage are the new owners of ACT! and simply saying that they are bringing in a new breath of fresh air would be a complete under-statement. To quote from one of my all-time favourite songs by AC/DC “Back in Black”:

Yes I’m let loose
From the noose
That’s kept me hanging about
I keep looking at the sky
‘Cause it’s getting me high
Forget the hearse ‘cos I’ll never die
I got nine lives, cats eyes
Using every one of them and running wild
‘cause I’m back!

..and wow is ACT! back…sorry that should be act! is back! From the very on-set of PA, both Bob and John set the scene for me with the single word “ENGAGEMENT”. When Swiftpage talk about engagement, they want to re-engage with the product, re-engage with the platform, re-engage with partners, re-engage with add-on partners, re-engage with ex-Sage employees, re-engage with end-users and re-engage with the entire product vision! For once I genuinely believe that this is not the usual vacuous marketing led  series of hollow promises. I, and many others, had the pleasure of having direct conversation time with each member of the senior executive and management team that were present at Perfecting ACT!. This level of commitment from their busy schedules would have been unparalleled during Sage’s tenure. Every member of Swiftpage I spoke with had the same level of energy and enthusiasm that we partners have had for the product and they genuinely wanted to hear from us. We are all Swifities now, part of the team and in from the cold!

So that’s the euphoria part done with, what can we expect for the immediate and medium term future?

  1. We ACT! 2014 has been renamed and re-branded to act! v16, what this means is that this will not only be the final version of ACT! that Sage was involved in, but also the last 12 month product cycle release. Yes you understood that correctly, act! will no longer be released every 12 months but will settle down to longer version releases with smaller more frequent Service Pack/ update releases. This one thing alone will remove much of the pain that has been associated with the act! product for many years now, and will allow the product to adapt to a constantly changing landscape.
  2. A SaaS version of act! is due imminently based on the Swiftpage Engage Engine. The little that I saw of this edition still in it’s early stages of development, was a much simpler and cleaner version of act! Professional with just the core Contact Management functionality.
  3. Consolidation of all regional sectors outside of North America into a single office based in Newcastle-Upon-Tyne in the UK, and a thorough commitment that regional issues and impacts of version and update roll-outs will be given equal weighting within product design, vision and support.

For us ACCs in the UK, the request for an increased level of communication and involvement with the senior management headed by Dan Ogden and Guy Clack is such refreshing news that the voices of all the clients we represent will now not go unnoticed or unheard. An early indication of this was the dramatically increased level of activity and meetings Dan and Guy had with French partners prior to PA to ensure that a French version of ACT! 2013 was made available after a failure by Sage to ensure that ACT! 2013 was released in French.

So here’s to a bright new orange future with Swiftpage and a return of Perfecting ACT! as a central opportunity for all act! business partners globally to meet, learn and above all ENGAGE!

Update ACT! Phone Formats via SQL

Field Phone Military

I saw a request on the public ACT! Community Forums from a user asking if there was a way to carry out a batch update of Phone Field formats throughout an ACT! dB. This is a fairly common request and something that can cause much heart ache for ACT! Users. In many cases an innocent User may update a Phone Field with a new display format and loose the phone number, the easy work-around to this is to simply copy-paste the number back, but it is of concern that if a User is not aware of this bug or “known-issue” data can be lost. The other problem is that you can only employ this method on single field at a time which is a very repetitive, tedious and frustrating exercise. We’ve written small utility apps that do this in the past for clients and there are other plugins/add-ons available both free and paid for that can do this, but I thought it would be interesting as a blog article to show how quickly and simply this can be done via SQL. Obviously the usual caveats apply that this should not be done without exercising extreme caution and care and I wouldn’t always recommend doing this within a synch environment (however the update triggers for synch are activated by the update).

There are basically 2 tables involved with storing Phone field data within the ACT dB:

  • TBL_PHONE
  • TBLPHONEMASK

The TBL_PHONE as you would expect stores the phone data and the TBL_PHONEMASK records the various Phone display masks or formats within the dB. Within the relational model for ACT!, if an entity such as Contact, Company, Group or Opportunity has a Phone field, it will have a row within the TBL_PHONE table relating back to it via the CONTACTID, COMPANYID, GROUPID or OPPORTUNITYID column. Below is an example of the relationship between the CONTACT-PHONE-PHONEMASK tables.

Contact-Phone-PhoneMask relationship

The relationship between the Contact, Phone and PhoneMask tables

In the example I am using for this article, we have our ACT! dB Contacts that are in free-form format, we would like to apply a new phone format to all UK Contacts with the following mask: (####) ### #### . To make things easy we create this format within the ACT! application. We can then go into our SQL query editor and type the simple query:

SELECT PHONEMASKID
FROM TBL_PHONEMASK
WHERE PHONEMASK='(####) ### ####'

This will give us the unique ID of the new Phone Mask. Either copy or note it down as we will need it for the next stage. We would like to make this Phone Mask the default format for all new phone numbers so we need to set the value for the ISDEFAULT field in the TBL_PHONEMASK table as 1 and then we want to update the entire TBL_PHONE table to use this mask for any phone number within the UK which has the country code of 44 (the USA is 1). The following code shows the final SQL statement that will update the dB.

   1:  UPDATE TBL_PHONEMASK
   2:  SET ISDEFAULT =1
   3:  WHERE PHONEMASKID='BC13A500-E182-4663-AC30-06C5E119BDEA'
   4:  UPDATE TBL_PHONE
   5:  SET PHONEMASKID = 'BC13A500-E182-4663-AC30-06C5E119BDEA'
   6:  WHERE COUNTRYCODE=44

Line 3 uses the unique ID for this mask within my dB which will most probably be different in your dBs. The statements between lines 1-3 set this mask as the default mask in the TBL_PHONEMASK table and lines 4-6 update the TBL_PHONE table to use the new Phone Mask.

Once you have run the SQL, you just have to refresh the ACT! application view and you will see your new format in place. Hopefully you have found this helpful or at least interesting!