none
String format is different with languages strings RRS feed

  • Question

  • My program creates a text file and prints line after line with string formatting, like that:

                    sw.WriteLine( $"|{cnt,3}|" + $" ID: {p.ID}|" + $" {p.Name,15}|" +
                        $" {p.Sex} |" + $" {p.Birthday}|" + " Dead: " + p.Dead);

    I was hoping to get a look of a table. However, some of the names (p.Name) are in Hebrew and some in English.

    The English ones behave perfectly - well aligned in size.

    The Hebrew ones are not aligned - some by one character (to the left), sometimes 2 or even more to the left.

    BTW - the fields that have no pre-decided width are fixed size anyway.

    Any idea why? how can I fix that?

    Thank you

    Yigal

    Monday, March 4, 2019 12:30 PM

Answers

  • Hi, <g class="gr_ gr_21 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace" data-gr-id="21" id="21">YigalB</g>

    Thank you for posting here.

    Based on your last reply, you want to export directly to a table in a word file.

    First, it is best for you to install <g class="gr_ gr_22 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep" data-gr-id="22" id="22">DocX</g> library<g class="gr_ gr_23 gr-alert gr_gramm gr_inline_cards gr_run_anim Style replaceWithoutSep" data-gr-id="23" id="23">.(</g> In solution explorer, right click on References >> Manage NuGet Packages.)

    Then, you could try the following code to get it.

    static void Main(string[] args)
            {
                string path = "D:\\example.docx";
                var doc = DocX.Create(path);
                Table table = doc.AddTable(2, 6);
                table.Alignment = Alignment.center;
                table.Rows[0].Cells[0].Paragraphs.First().Append("ID");
                table.Rows[0].Cells[1].Paragraphs.First().Append("first Name");
                table.Rows[0].Cells[2].Paragraphs.First().Append("Sex");
                table.Rows[0].Cells[3].Paragraphs.First().Append("Birthday");
                table.Rows[0].Cells[4].Paragraphs.First().Append("Deadday");
                table.Rows[0].Cells[5].Paragraphs.First().Append("LastName");
                table.Rows[1].Cells[0].Paragraphs.First().Append("1001");
                table.Rows[1].Cells[1].Paragraphs.First().Append("שמח");
                table.Rows[1].Cells[2].Paragraphs.First().Append("male");
                table.Rows[1].Cells[3].Paragraphs.First().Append("2019-03-05");
                table.Rows[1].Cells[4].Paragraphs.First().Append("2119-03-05");
                table.Rows[1].Cells[5].Paragraphs.First().Append("אל תדאג");
                doc.InsertTable(table);
                doc.Save();
                Console.WriteLine("success");
                Console.ReadKey();
            }

    Result:

    Hope my solution could be helpful.

    Best regards,

    Jack



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Tuesday, March 5, 2019 6:12 AM
    Moderator
  • Hi YigalB,

    You could refer to the following link to add the reference correctly.

    https://www.c-sharpcorner.com/article/generate-word-document-using-c-sharp/

    Note: This response contains a reference to a third-party World Wide Web site. Microsoft is providing this information as a convenience to you.

    Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there.

    There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thursday, March 7, 2019 1:23 AM
    Moderator

All replies

  • The string is in Unicode so it doesn't matter what the underlying values are. They can all go in the same string. However the data needs to be read into the string using the appropriate locale and I suspect you aren't doing that properly. Note also that formatting would be independent of the string concat you're doing. Try starting with a simple String.Format call and get it working there. That is ultimately what string interpolation does anyway. You may also need to specify the specific culture in the call to String.Format otherwise it'll use the current culture's formatting which may not be correct if you're dealing with data from other cultures.

    Michael Taylor http://www.michaeltaylorp3.net


    Monday, March 4, 2019 2:53 PM
    Moderator
  • Thanks Michael for the fast answer.

    Perhaps I didn't explain well: I can read the string and get the right characterless. The issue is with the space taken by the 15 characters space dedicated to the name in this case. 

    I was sure that that 15 characters in English will take the same width as with English, right? 

    I was counting on that in order to print a nice table view in text file. 

    Or perhaps the question should be: how should I create an output file with a table ?

    Monday, March 4, 2019 3:39 PM
  • "I was sure that that 15 characters in English will take the same width as with English, right? :

    No that isn't correct. Even within a font characters vary in width. A `Q` is quite a bit wider than an `l`. This is where font size comes into play. When you start changing cultures then the differences can be quite striking.

    I'm not a Unicode expert so take everything after this with a grain of salt.  Unicode supports multiple languages and each language may use different character "widths". In Unicode, for example, a character can be 0-2 "characters" wide depending upon the language. So counting characters to determine width only works in cultures where this isn't an issue (e.g. English). Other languages (e.g. Hebrew, many RTL languages) don't follow this rule so 10 characters in English may be several "character widths" wider in another language. Refer to this interesting bug report in GitHub about the details.

    Back to your question. In general we aren't mixing cultures so we simply use a width that is appropriate for the largest string we expect to store in a "column". If you're going to be mixing cultures then you'll need to adjust the table accordingly. You might start by just adding a little more padding to the table. For example if you know that the max name length is 8 then pad the column to 12 or 16. There may be occasions where it doesn't fit right. If you need absolute table sizes then you'd need to "render" the table using the font and display you want and then detect that a string doesn't fit. This seems like a lot of work though. Alternatively you could just print the first X characters irrelevant of the culture. This guarantees a consistent table layout with "long" names being truncated.

    Of course the best answer may be to forego the table altogether if you cannot get a consistent layout and it is important. A table structure makes it easier to read for a user but not for reading from programs. If this is a data file then leave the data in the raw and let the UI (which can handle differing characters widths better) handle the table display.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, March 4, 2019 4:24 PM
    Moderator

  • I was sure that that 15 characters in English will take the same width as with English, right? 


    I think you meant to say "Hebrew" instead of "English" once in that statement.

    It's not at all clear where you are seeing the difference in width. How are
    you displaying the data from the file? In general, the width used by each
    character will depend on the font in use. If a variable-pitch (proportional)
    font is being used then different characters will often have different widths. 
    By "width" what is meant is the visible space between characters.
    Examples are Arial, Courier

    If a fixed-pitch (mono-spaced) font is used then each character will use 
    the same width when displayed. Example fonts are FixedSys, Console, Lucida,
    Courier New

    Note that some fonts may not include Hebrew characters.

    If you can change the font in whatever you are using to view the data then
    try Courier New. 

    "Monospaced and proportional refer to the distance between each character in 
    a font. Monospaced fonts have constant spacing between characters while 
    proportional fonts have variable spacing between characters."

    - Wayne

    Monday, March 4, 2019 6:00 PM
  •  You may also need to specify the specific culture in the call to String.Format otherwise it'll use the correct culture's formatting 

    Did you mean to say "it'll use the current culture"?

    - Wayne

    Monday, March 4, 2019 6:05 PM
  • Fixed

    Michael Taylor http://www.michaeltaylorp3.net

    Monday, March 4, 2019 6:46 PM
    Moderator
  • Let me take a step backwards:

    My application has a list of names, each name with fields like ID, first name, last name, birth date, etc.

    The target (one of them) is to create a list in a shape of a table. I use a text file for that because it is easy at this time for a newbie (although I wish I knew how to generate a table with word file, which should be a better solution)

    I was hoping to create a table look by using the '|' character between the fields, allocating a fixed number of character to each field every line. 

    With English characters, it looks very good, regardless of the names length. All lines have the '|' separator exactly at same location. 

    With Hebrew characters it is totally different - the location of the '\' is changing with every name. So Even if I could "blame" the font size, how come all English names occupy same width while Hebrew ones vary?

    Is there a way to export directly to a table in a word file? If yes, I will not need to solve the problem. If creating the table is an issue, I can always create a template.

    Yigal

    Monday, March 4, 2019 7:00 PM
  • Yes you can create a table in Word pretty easily. But as far as how easy it is it depends upon the format of "My application has a list of names, each name with fields like ID, first name, last name, birth date, etc."

    If you already have this data in a file that is | separated then use a text delimited reader to read the data in. Then you can send it to whatever you need. If it is coming from a DB then you can use ADO.NET to write it to the table in Word.


    Michael Taylor http://www.michaeltaylorp3.net

    Monday, March 4, 2019 7:08 PM
    Moderator
  • Hi, <g class="gr_ gr_21 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace" data-gr-id="21" id="21">YigalB</g>

    Thank you for posting here.

    Based on your last reply, you want to export directly to a table in a word file.

    First, it is best for you to install <g class="gr_ gr_22 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep" data-gr-id="22" id="22">DocX</g> library<g class="gr_ gr_23 gr-alert gr_gramm gr_inline_cards gr_run_anim Style replaceWithoutSep" data-gr-id="23" id="23">.(</g> In solution explorer, right click on References >> Manage NuGet Packages.)

    Then, you could try the following code to get it.

    static void Main(string[] args)
            {
                string path = "D:\\example.docx";
                var doc = DocX.Create(path);
                Table table = doc.AddTable(2, 6);
                table.Alignment = Alignment.center;
                table.Rows[0].Cells[0].Paragraphs.First().Append("ID");
                table.Rows[0].Cells[1].Paragraphs.First().Append("first Name");
                table.Rows[0].Cells[2].Paragraphs.First().Append("Sex");
                table.Rows[0].Cells[3].Paragraphs.First().Append("Birthday");
                table.Rows[0].Cells[4].Paragraphs.First().Append("Deadday");
                table.Rows[0].Cells[5].Paragraphs.First().Append("LastName");
                table.Rows[1].Cells[0].Paragraphs.First().Append("1001");
                table.Rows[1].Cells[1].Paragraphs.First().Append("שמח");
                table.Rows[1].Cells[2].Paragraphs.First().Append("male");
                table.Rows[1].Cells[3].Paragraphs.First().Append("2019-03-05");
                table.Rows[1].Cells[4].Paragraphs.First().Append("2119-03-05");
                table.Rows[1].Cells[5].Paragraphs.First().Append("אל תדאג");
                doc.InsertTable(table);
                doc.Save();
                Console.WriteLine("success");
                Console.ReadKey();
            }

    Result:

    Hope my solution could be helpful.

    Best regards,

    Jack



    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Tuesday, March 5, 2019 6:12 AM
    Moderator
  • Hi

    Is your problem solved? If so, please post "Mark as answer" to the appropriate answer , so that it will help other members to find solution quickly if they faces similar issue.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, March 6, 2019 8:59 AM
    Moderator
  • Toda Jack.

    Seems like a perfect solution.

    I added DocX in NuGet.

    Then I added the code, yet I have compile errors on DOCX (does not exist in current content) - probably missing a library.

    Thanks to Google, I noticed I need to add a reference to Microsoft Word Object Library. So I did, but the error is still there.

    Yigal


    • Edited by YigalB Wednesday, March 6, 2019 11:59 AM
    Wednesday, March 6, 2019 10:28 AM
  • Hi YigalB,

    You could refer to the following link to add the reference correctly.

    https://www.c-sharpcorner.com/article/generate-word-document-using-c-sharp/

    Note: This response contains a reference to a third-party World Wide Web site. Microsoft is providing this information as a convenience to you.

    Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there.

    There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best Regards,

    Jack


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Thursday, March 7, 2019 1:23 AM
    Moderator
  • Thanks Jack!

    Works like charm.

    Yigal

    Thursday, March 7, 2019 6:33 AM
  • Hi again

    The Hebrew strings (names) are not presented in the right order. For example if the string includes a first name and last name afterwards, it is presented in the wrong order.

    It gets worst if 3 names exists.

    How can I make the string presented as it is?

    Thursday, March 7, 2019 2:16 PM