convert memo field in Access database from double byte to Unicode - sql-server

I am using Access database for one system, and SQL server for another system. The data gets synced between these two systems.
The problem is that one of the fields in a table in Access database is a Memo field which is in double-byte format. When I read this data using DataGridView in a Windows form, the text is displayed as ???.
Also, when data from this field is inserted in sql server database nvarchar(max) field, non-English characters are inserted as ???.
How can I fetch data from memo field, convert its encoding to Unicode, so that it appears correctly in SQL server database as well?
Please help!!!

I have no direct experience with datagrid controls, but I already noticed that some database values are not correctly displayed through MS-Access controls. Uniqueidentifiers, for example, are set to '?????' values when displayed on a form. You could try this in the debug window, where "myIdField" control is bound to "myIdField" field from the underlying recordset (unique Identifier type field):
? screen.activeForm.recordset.fields("myIdField")
{F0E3C822-BEE9-474F-8A4D-445A33F363EE}
? screen.activeForm.controls("myIdField")
????
Here is what the Access Help says on this issue:
The Microsoft Jet database engine stores GUIDs as
arrays of type Byte. However, Microsoft Access can't return Byte data
from a control on a form or report. In order to return the value of a
GUID from a control, you must convert it to a string. To convert a
GUID to a string, use the StringFromGUID function. To convert a string
back to a GUID, use the GUIDFromString function.
So if you are extracting values from controls to update a table (either directly or through a recordset), you might face similar issuers ...
One solution will be to update data directly from the recordset original value. Another option would be to open the original recordset with a query containing necessary conversion instructions so that the field will be correctly displayed through the control.
What I usually do in similar situation, where I have to manipulate uniqueIdentifier fields from multiple datasources (MS-Access and SQL Server for Example), is to 'standardize' these fields as text in the recordsets. Recordsets are then built with queries such as:
SQL Server
"SELECT convert(nvarchar(36),myIdField) as myIdField, .... FROM .... "
MS-Access
"SELECT stringFromGUID(myIdField) as myIdField, .... FROM .... "

I solved this issue by converting the encoding as follows:
//Define Windows 1252, Big5 and Unicode encodings
System.Text.Encoding enc1252 = System.Text.Encoding.GetEncoding(1252);
System.Text.Encoding encBig5 = System.Text.Encoding.GetEncoding(950);
System.Text.Encoding encUTF16 = System.Text.Encoding.Unicode;
byte[] arrByte1 = enc1252.GetBytes(note); //string to be converted
byte[] arrByte2 = System.Text.Encoding.Convert(encBig5, encUTF16, arrByte1);
string convertedText = encUTF16.GetString(arrByte2);
return convertedText;
Thank you all for pitching in!

Related

how to add command for carriage return ssrs to msword

Goal: To print a mailmerge report with one of the cell with 3 persons contact information ( with each person having name, cell, email)
Issue: All the data is junked up as we trying to display contact data in contact column and it is not persisting the carriage returns from procedure or ssrs.
In our application I am sending data from SSRS report and printing reports in MS Word (Mail Merge)
As I am sending data in one of the table a value which is brought from database is long and formatted. But the formatting is not persisting as the data is passed from ssrs to ms word(xml) via common reporting services.
I tried adding vbcrf / tried formatting data result from stored procedure/ tried adding /n/r as a string while sending the data from ssrs to services none of them are working.
The report looks odd because in one cell all the data is clumsy and has no carriage returns where necessary. I can't do this in separate cells since this is relevant to that column alone.
Thanks in advance.
A line break in Microsoft Word is represented by a vertical tab - ASCII 11, Ctrl-K, or escape code \v.

SQL Server Datetime object persistent reformatting issue in Excel

I have an annoying issue working with SQL Server DATETIME objects in Excel 2013. The problem has been stated several times here in SO, and I know that the work around is to just reformat the DATETIME objects in Excel by doing this:
Right click the cell
Choose Format Cells
Choose Custom
In the Type: input field enter yyyy-mm-dd hh:mm:ss.000
This works fine BUT I loathe having to do this every time. Is there a permanent work around to this aside from creating macros? I need to maintain the granularity of the DATETIME object so I cannot use a SMALLDATETIME. I am currently using Microsoft SQL Server Management Studio 2008 r2 on a win7 machine.
Thanks in advance.
-Stelio K.
Without any code it's hard to guess how the data gets from SQL Server to Excel. I assume it's not through a data connection, because Excel wouldn't have any issues displaying the data as dates directly.
What about data connections?
Excel doesn't support any kind of formatting or any useful designer for that matter, when working with data connections only. That functionality is provided by Power Query or the PivotTable designer. Power Query is integrated in Excel 2016 and available as a download for Excel 2010+.
Why you need to format dates
Excel doesn't preserve type information. Everything is a string or number and its display is governed by the cell's format.
Dates are stored as decimals using the OLE Automation format - the integral part is the number of dates since 1900-01-01 and the fractional part is the time. This is why the System.DateTime has those FromOADate and ToOADate functions.
To create an Excel sheet with dates, you should set the cell format at the same time you generate the cell.
How to format cells
Doing this is relatively if you use the Open XML SDK or a library like EPPlus. The following example creates an Excel sheet from a list of customers:
static void Main(string[] args)
{
var customers = new[]
{
new Customer("A",DateTime.Now),
new Customer("B",DateTime.Today.AddDays(-1))
};
File.Delete("customers.xlsx");
var newFile = new FileInfo(#"customers.xlsx");
using (ExcelPackage pck = new ExcelPackage(newFile))
{
var ws = pck.Workbook.Worksheets.Add("Content");
// This format string *is* affected by the user locale!
// and so is "mm-dd-yy"!
ws.Column(2).Style.Numberformat.Format = "m/d/yy h:mm";
//That's all it needs to load the data
ws.Cells.LoadFromCollection(customers,true);
pck.Save();
}
}
The code uses the LoadFromCollection method to load a list of customers directly, without dealing with cells. true means that a header is generated.
There are equivalent methods to load data from other source: LoadFromDatatable, LoadFromDataReader, LoadFromText for CSV data and even LoadFromArrays for jagged object arrays.
The weird thing is that specifying the m/d/yy h:mm or mm-dd-yy format uses the user's locale for formatting, not the US format! That's because these formats are built-in into Excel and are treated as the locale-dependent formats. In the list of date formats they are shown with an asterisk, meaning they are affected by the user's locale.
The reason for this weirdness is that when Excel moved to the XML-based XLSX format 10 years ago, it preserved the quirks of the older XLS format for backward-compatibility reasons.
When EPPlus saves the xlsx file it detects them and stores a reference to the built-in format ID (22 and 14 respectively) instead of storing the entire format string.
Finding Format IDs
The list of standard format IDs is shown in the NumberingFormat element documentation page of the Open XML standard. Excel originally defined IDs 0 (General) through 49.
EPPlus doesn't allow setting the ID directly. It checks the format string and maps only the formats 0-49 as shown in the GetBfromBuildIdFromFormat method of ExcelNumberFormat. In order to get ID 22 we need to set the Format property to "m/d/yy h:mm"
Another trick is to check the stylesheets of an existing sheet. xlsx is a zipped package of XML files that can be opened with any decompression utility. The styles are stored in the xl\styles.xml file.

Delphi stream to/from database with FireDAC

Originaly I want to save/retrieve report from fastreports which uses SaveToStream/LoadToStream for this purpose. I use RAD Studio XE6(upd1).
In database I have table Reports with index field 'StVn'type int and field 'Definition' type ntext. Database is MSSQL and for saving report I use:
FDCommand.CommandText.Text:='UPDATE Reports SET Definition= :pDefinition WHERE StVn=1';
FDCommand.Params.ParamByName('pDefinition').LoadFromStream(MyStream, ftWidememo);
FDCommand.Execute;
and for retrieving:
FDQuery.SQL.Text:='SELECT * FROM Reports WHERE StVn=1';
FDQuery.Open();
MyStream:=FDQuery.CreateBlobStream(FDQuery.FieldByName('Definition'),bmRead);
This worked for some short reports, but for any real one saving/restoring corrupts report definition.
So I make an test case on new form with just an Memo and tried to save/restore it with same data acess setup (FDConnection, FDCommand, FDQuery) and following code:
procedure TForm1.BMemoSaveClick(Sender: TObject);
var TmpStream:TStream;
begin
TmpStream:=TMemoryStream.Create;
Memo1.Lines.SaveToStream(TmpStream);
ShowMessage(IntToStr(TmpStream.Size));
FDCommand1.Params.Clear;
FDCommand1.CommandText.Text:='UPDATE Reports SET Definition= :pDefinition WHERE StVn=1';
FDCommand1.Params.ParamByName('pDefinition').LoadFromStream(TmpStream,ftWideMemo);
FDCommand1.Execute();
TmpStream.Free;
end;
procedure TForm1.BMemoLoadClick(Sender: TObject);
var TmpStream:TStream;
begin
FDQuery.SQL.Text:='SELECT * FROM Reports WHERE StVn=1';
FDQuery.Open();
TmpStream:=FDQuery.CreateBlobStream(FDQuery.FieldByName('Definition'),bmRead);
ShowMessage(IntToStr(TmpStream.Size));
Memo1.Lines.LoadFromStream(TmpStream);
TmpStream.Free;
end;
As you can see I have inserted ShowMessage to see the stream size at saving and at retrieving and if I save just default text 'Memo1' I get length of 7 at saving and length of 14 at loading the memo (it is allways doubled).
Any ideas what I am doing wrong ?
Note, I have not verified the database saving/loading as I don't have MSSQL, but I'm pretty sure this is the cause:
By default, TString uses the default encoding (TEncoding.Default), which is most likely ANSI (in my case Windows-1252), hence the length for the memo text showing as 7 bytes: 5 for "Memo1" and two for the CRLF.
However, your column is of type NTEXT which stores text as UTF-16. When you read it back you do so as a blob and FireDAC does not perform any character conversion1 then, hence the doubling in size.
I would suggest you treat the report as binary data and store it as such using an "image" type column and use ftBlob instead of ftWideMemo.

How to read Arabic characters from varchar datatype?

I have an old system that uses varchar datatype in its database to store Arabic names, now the names appear in the database like this:
"ãíÓÇÁ ÇáãÈíÖíä"
Now I am building a new system using VB.NET, how can I read these names to appear in Arabic characters?
Also I need to point out here that the old system even it stores the data as I mentioned earlier it converts the characters in a correct format.
How to display it properly in the new system and in the SQL Server Management Studio?
have you tried nvarchar? you may find some usefull information at the link below
When must we use NVARCHAR/NCHAR instead of VARCHAR/CHAR in SQL Server?
I faced the same Problem, and I solved it by two steps:
1.change the datatype of the column in DB into nvarchar
2.use the encoding to change the data into Arabic
I used the following function
private string GetDataWithArabic(string srcData)
{
Encoding iso = Encoding.GetEncoding("iso-8859-1");
Encoding unicode = Encoding.Default;
byte[] unicodeBytes = iso.GetBytes(srcData);
return unicode.GetString(unicodeBytes);
}
but make sure you use this method once on DB data, because it will corrupt the data if used twice
I think your answer is here: "storing and retrieving non english characters" http://aalamrangi.wordpress.com/2012/05/13/storing-and-retrieving-non-english-unicode-characters-hindi-czech-arabic-etc-in-sql-server/

T-SQL - text field to nvarchar

I have a 'text' type in a SQL table (BigNote), and a new nvarchar(2000) field (LittleNote).
I need to save the first 2000 characters from the #BigNote into the LittleNote field within a stored procedure. Can someone share some thoughts?
Do I need to check for:
- nulls?
- the BigNote length and only grab the exact amount?
It is working by just assigning LittleNote = #BigNote, but I want to avoid problems when the text is too big etc...
Once we release an update to the application, we will handle this more elegantly, but in the meantime we need to get a non-Text field with this data in the database.
you could use
LittleNote = CONVERT(NVARCHAR(2000), #BigNote)
or with SUBSTRING
LittleNote = SUBSTRING(#BigNote, 1, 2000)

Resources