function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Tom.ax53Tom.ax53 

id returned by api 3.0

Hello All,

I have a strange issue when creating new accounts using the new api 3.0 in VB.NET.

The id property of the returned insert result is completely other value than the ID the record actually gets to have in salesforce.com

eg I create an account using the api and the id returned is 00120000000i5znAAA, but the id in salesforce.com of the exact same record is 00120000000i5zn ??

This is what i'm doing:

Dim insertobjects() As sForceConn.sObject = {newaccount}

Dim ret() As sForceConn.SaveResult

Try

ret = sForce.create(insertobjects)

Catch

MsgBox(Err.Description)

Return False

End Try

sfdc_id = ret(0).id

DevAngelDevAngel

Hi Tom,

As one of the more recent user's of the API you would not be aware that the ids are the same.  The reason that they are the same is that it was discovered in previous versions, that some client applications don't handle case-sensitive primary keys.  The solution resulted in 2 "forms" of an ID.  One is 15 characters and is case-sesnistive, the other is 18 and is not case-sensitive.  If you remove the last 3 chars from the right hand side of the 18 char id, you will have the 15 char id.  In the API you can use either form, in fact, when using wils or other techniques that obtain ids from the ui, they will be 15 char.  You can use the 15 char id anywhere you use the 18.

There is a an algorithm posted on these boards that explains how to obtain an 18 char id from a 15, but you should not need it.

Cheers

Tom.ax53Tom.ax53
Thanks !
Tony JTony J

As a little help, here is some C# code that implements the algrotihm described elsewhere on this board to convert a 15 char salesforce ID into an 18 char salesforce ID:  It should work OK....

public string ConvertShortIDToLongID(string shortID)

{

string AdditionalChars = "";

//First construct the mapping array

string[] Mapping = new System.String[32];

//First put in the chars "A" to "Z"

for(int i=65;i<91;i++)

{

Mapping[i-65] = System.Convert.ToString((char) i);

}

//Now put in the chars "0" to "5"

for(int i=48;i<54;i++)

{

Mapping[i-22] = System.Convert.ToString((char) i);

}

for(int i=0;i<3;i++)

{

//Convert the portion of the string to string containing a bitmask

string BitString = ConvertChunkToBitString(shortID.ToCharArray(i*5,5));

//Now convery this string to a byte using the binary base

byte myByte = System.Convert.ToByte(BitString,2);

//Get the mapping char from the mapping array and add to additional chars

AdditionalChars+=Mapping[(int) myByte];

}

return shortID + AdditionalChars;

}

private string ConvertChunkToBitString(char[] chunk)

{

string BitString = "";

//Convert the char array to a 5 character string, indicating whether the case is upper or otherwise

//Start from the right hand side of the char array, and put 1 in the result string if the char is uppercase,

//put 0 in the result string otherwise

for(int i=4;i>=0;i--)

{

BitString+= (System.Char.IsUpper(chunk[i]) ? "1" : "0");

}

return BitString;

}

ScotScot

As stated earlier, you probably don't need it for use with the API (you can truncate to 15 characters), but if you want to work with backup files or excel extracts, you will ... since the 18 char version is only available through the api ...

So, here is a version using VB:

Function FixID(InID As String) As String
' Converts a 15 character ID to an 18 character, case-insensitive one ...
Dim InChars As String, InI As Integer, InUpper As String
Dim InCnt As Integer
InChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345"
InUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

InCnt = 0
For InI = 15 To 1 Step -1
   InCnt = 2 * InCnt + Sgn(InStr(1, InUpper, Mid(InID, InI, 1), vbBinaryCompare))
   If InI Mod 5 = 1 Then
       FixID = Mid(InChars, InCnt + 1, 1) + FixID
       InCnt = 0
       End If
    Next InI
    FixID = InID + FixID
End Function

Ron HessRon Hess

Boy was this handy today !

thanks

JessicaJessica

Has anyone tested this VB version. I have built the code around this Function however, it takes my 15 digit ID and gives me a 5 digit ID.

Ex: 00120000000jARB is updated to IDBY5- Below is the code I used to update the field. Can anyone let me know if I did something wrong, or if it is an issue with the FixID Function.

This is pulling the table name and the field name of the ID field from a MS Access form. The table and the field are being referenced correctly, since I can step through and the value at the end of each step is correct. However, when I get to the conversion I have an issue.

Any help is GREATLY appreciated.

Public Function UpdateID_InTable(strTable As String, strFld As String) As Boolean
On Error GoTo lblErr
Dim db As Database, rs As Recordset

Set db = DBEngine(0)(0)
Set rs = db.OpenRecordset(strTable, dbOpenDynaset)

Do While Not rs.EOF
    With rs
        .Edit
        rs(strFld) = FixID(strFld)
        .Update
        .MoveNext
    End With
Loop

Ron WildRon Wild
Here's a PHP sample that can be run as a web service (returning your converted 18 char id in a JSON string):

This PHP sample can be run as a web service, returning a JSON string with an 18 char version of a 15 char id:

//
// Responds to AJAX requests with a normalized version of a 15 character Salesforce ID
//
header("Cache-Control: no-cache, must-revalidate");
// Date in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");

$id = $_REQUEST['sfid'];
$error = false;
$values = array();

// fluff up a 15 char id to return an 18 char id
if ($id == null) {
$error = true;
$message = "sfid=null, please provide a 15 character Salesforce Id.";
}
if (strlen($id) != 15) {
$error = true;
$message = "SFID is not 15 characters long.";
}

if (!$error) {
$suffix = "";
for ($i = 0; $i < 3; $i++) { // for each group of 5 characters
$flags = 0;
for ($j = 0; $j < 5; $j++) { // for each character
$c = substr($id,($i * 5 + $j),1);
if (strpos("ABCDEFGHIJKLMNOPQRSTUVWXYZ",$c)) {
// $flags += pow(2,j);
$flags += 1 << $j;
}
}
$suffix .= substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",$flags,1);
}
$longId = $id."".$suffix;
}
$values['short'] = $id;
$values['long'] = $longId;
if ($error) {
$values['message'] = $message;
}
echo "{ results: ".json_encode($values).", error: ".($error?"true":"false")."}";

?>
MaskMask
And here is the Perl version:

sub long_id{
    my $id = shift;
    my @id = split('',$id);
    my @bits;

    my @chars = ('A'..'Z','0'..'9');
    my $k = -1;
    for (my $i=0;$i<=$#id ;$i++) {
        if (!($i % 5)){$k++;$bits[$k]=0;}
        $bits[$k] += 2 ** ($i % 5) if $id[$i] =~ /^[A-Z]$/;
    }
    @bits = map {$chars[$_]} @bits;
    return $id.join('',@bits)."\n";
}