-2

I am looking for an example of how to set (and get) the number of digits (LOCALE_IDIGITS).

Background: I am using COM automation (client: Python, server: ACCESS, package:pywin32). When using TransferText it always prints 2 decimals. (See e.g. https://social.msdn.microsoft.com/Forums/office/en-US/5bba131c-d6cd-4548-9f0f-c85947b3d81d/access-2010-export-text-truncates-numbers-to-two-decimal-places?forum=accessdev for others hitting this problem). Actually, it turns out, this is due to the locale settings. (I could not find any documentation on this, but a bit of testing confirmed this.) Under Windows, the locale has a setting called LOCALE_IDIGITS:

Number of fractional digits placed after the decimal separator. The maximum number of characters allowed for this string is two, including a terminating null character. For example, 2 for 5.00, 1 for 5.0.

So, because of this, I want to change the locale settings for the application so the Access Function will write a CSV file in full precision (say 16 or 8 decimals). I don't mind if the example is in a different language or is changing a similar setting. I assume get and set will be symmetric, so one of these should be sufficient to get me going.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • 1
    *"write a CSV file in full precision"* - That'd require [767 digits](https://stackoverflow.com/a/62542806/1889329) for double precision floating point values. Is that what you really need, or is your requirement a different one (such as "without loss of information")? – IInspectable Mar 10 '23 at 11:19
  • @IInspectable read further and you see that I explicitly say that is not needed. Not so helpful this comment. – Erwin Kalvelagen Mar 10 '23 at 11:26
  • 1
    So then, what *is* your requirement? Just some arbitrary number of digits? – IInspectable Mar 10 '23 at 11:38
  • The requirement is to change the default of 2 into something else, like 8 or 16. – Erwin Kalvelagen Mar 10 '23 at 12:46

1 Answers1

0

This is the first part of the answer. The Get part in C++ is demonstrated here:

#include <Windows.h>
#include <Winnls.h>
#include <stdio.h>

int GetNumberOfDigitsForDecimal()
{
    const int stringsize = 2; // docs for LOCALE_IDIGITS says this won't be more than 2 including the null char

    wchar_t value[stringsize] = {};
    GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_NOUSEROVERRIDE|LOCALE_IDIGITS, value, stringsize);
    return _wtoi(value);
}

(source: Microsoft locale how to get no of digits after decimal place?) It is a bit strange to use a string to communicate a small integer. I suspect that is because most other locale settings are strings or characters.

As far as I can find, there is no corresponding SetLocaleInfoEx and the Python pywin32 package does not seem to have it (either get or set).

There is a SetLocaleInfoA (again not in pywin32), but the docs https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-setlocaleinfoa warn against using it:

Caution Because this function modifies values for all applications, it should only be called by the regional and language options functionality of Control Panel, or a similar utility. If making an international change to system parameters, the calling application must broadcast the WM_SETTINGCHANGE message to avoid causing instabilities in other applications.

I think this means there is no easy and reliable programmable way to set the number of decimals for TransferText.

Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39