How do I set maximum number of chars in a TDBCombobox? - delphi

A TBEdit control has MaxLength property, but you don't need to do anything with it, because being a data aware control this is handled automatically.
A TDBCombobox control has no such property and max length is not handled automatically.
How should control the maximum number of chars in a TDBCombobox when Style is set to csDropDown? Ideally this should be based upon the length of the underlying field.

I have a form where there are "standard" selections the user can choose, but they need to also be able to enter free-form instructions, and so I need to use csDropDown, so I've also noticed that TDBComboBox doesn't expose the MaxLength property that the standard TComboBox does, and it doesn't work just using the field size, as you've noticed.
The other problem is that if the user types in too much content, TDBComboBox just silently truncates it to the underlying column's size when updating it. The text still looks like it's all there until the data is posted (where the truncation occurs), but the DBComboBox.Text is not updated to reflect the truncation. Closing the window and then reopening it reveals the loss of data.
I work around this by using an interposer class to access the protected MaxLength property of the TCustomComboBox it descends from, to set the maximum length properly for the size of the TStringField:
type
THackCB = class(TCustomComboBox);
procedure TEditForm.FormShow(Sender: TObject);
begin
THackCB(TheDBComboBx).MaxLength := DataMod.MyStringField.Size;
end;

Related

Can TStringField be created with dynamic Size?

I have Insufficient memory error with TClientDataset with TStringField fields. I need to use length of strings from 0 to 8000 - but don't know what length will be until I fill the TClientDataset.
So, can TStringField be created with dynamic Size?
P.S. The initial task is to copy TDBGrid to TClientDataset.
What kind of data are you storing in those fields to need up to 8000 characters?
Imagine you do partial search on those fields using wildcards. I bet such search would take ages and could posibly even crash your database server.
Besides not all databases tables support 8192 character sized StringFields.
http://docwiki.embarcadero.com/Libraries/XE6/en/Data.DB.TStringField
TStringField encapsulates the fundamental behavior common to fields
that contain string data. A value of a string field is physically
stored as a sequence of up to 8192 characters. However, some table
types may only support string fields of smaller dimensions.
So why don't you use TMemoFields instead since they alow to have dynamical size of their text?
http://docwiki.embarcadero.com/Libraries/XE6/en/Data.DB.TMemoField
I have used the following solution. First, calculate maximum Sizes based on Length(aDBGrid.Columns[i].Field.DisplayText). Then create TStringFields with the calculated Sizes.
P.S. The initial task is to copy TDBGrid to TClientDataset.

Prevent Select All behavior of TInplaceEditer in TStringgrid

When selecting a cell in TStringGrid the entire cell contents are selected, with the cursor positioned at the end of the selection. This is a problem.
My grid is being populated via a Live Binding to a TADOConnnection to a FoxPro database, I have a TADODataSet with FieldDefs that include the Size and Datatype of the fields ,for instance:
object DSProtocol: TADODataSet
Connection = CONProtocol
CursorType = ctStatic
LockType = ltBatchOptimistic
CommandText = 'select jobc from protocol'
FieldDefs = <
item
Name = 'jobc'
Attributes = [faFixed]
DataType = ftFixedChar
Size = 200
end>
end
I am unable to change the underlying database schema. In most cases the fields are way oversized for the information stored, the largest length value stored in jobc is 8 characters long, and will probably never be more than 10.
For the UI then, I have no reason to size the column holding jobc to show 200 characters, I just need it big enough to show 10. However, the TStringGrid cell is filled with the contents of that field plus enough space characters to pad it to 200. (Why? I don't know.) When selecting, the entire contents are selected, the cursor is placed at the end of the selection, and the end result is that it looks like the contents disappeared.
It does not seem like I can use any of the TSTringGrid events to override this behavior.
I attempted a quick and dirty fix of adding the (deprecated):
keybd_event(VK_HOME, 0, 0, 0);
keybd_event(VK_HOME, 0, KEYEVENTF_KEYUP, 0);
to the OnGetEditMask event, but this event appears to be called multiple times when starting editing and when completing editing. Thankfully this did not work, as I would have been tempted to leave it in...
I've attempted to trace back through the parent classes to determine exactly where the select all is being called but got lost tracing through asm code in the system unit. I read you can add a D- compiler directive to a unit to have the debugger skip over those units, but I'm really hesitant about modifying any of the VCL units for obvious reasons.
Looking for any solution at this point (modify sql query? live binding property? field property?) but ideally would like to know exactly where this happens so that I can store the initial value of the cell at the same time. (I want to add the normal spreadsheet-type behavior of escape-while-editing restores initial value).
It looks like the class chain I need to follow is TInplaceEdit -> TCustomMaskEdit -> TCustomEdit -> TWinControl I assume it's in there somewhere.

TADQuery with calculated field of blob type in Delphi

I am using Anydac components to access database. TADOQuery is for selecting of data from SQL database.
One of the fields is text, but I need to display some RTF instead of this text (same text but with highlighted words, etc). I tried to create calculated field of BLOB type and fill it with correct value (original text from DB + some processing) in OnCalcFields event of TADQuery. But it doesn't work. I get AV on start of app:
"Field 'xxx' cannot be a calculated or lookup field.".
If I change FieldKind property to fkInternalCalc (default value is fkCalculated) then app starts, but then I get AV at OnCalcFields when try to set value:
"Dataset not in edit or insert mode."
If I define calculated string field (instead of BLOB field), then everything is ok, but string type has another problem. For string type I have to provide Size property limiting max size of the text. And if I use value above 64k, for example 67000, I get AV when try to assign value (even short value!) at OnCalcFields event handler:
Project xxx.exe raised exception class $C0000005 with message "access violation at 0x004094fc: read of address 0xfffffffc".
So, I can create neither calculated BLOB field nor calculated string field. (It is limited in max size and there is no information what maximum size is really safe. I found problem with size >64k, but not sure it will be stable with smaller blocks.)
Any ideas what I am doing wrong?
Update: At moment I have implemented it in a different way. I replace data on presentation layer, but it is just a workaround and question is still here. Is it possible to use calculated fields of BLOB type in Delphi (preferably with Anydac TADQuery)? Is there any information regarding to limitations on calculated fields of string type (or maybe someone has experience how to avoid them)?
procedure TDBDM.CommentsCalcFields(DataSet: TDataSet);
begin
CommentsHighlighted.AsString := 'test';
end;
So, TADQuery has some SQL query, some fields defined + 1 calculated field of BLOB type + OnCalcFields event handler (code is above). It generates AV when I start app (and try to open query). Other things I tried were described earlier.

To set a value on a PowerBuilder textbox

I am developing a billing system using PowerBuilder 12.5 Classic and I need to set 0 for a textbox; like in vb.net txtchange.Text = 0
i have two drop down list boxes
ddlb_price (defines the price value of an item)
ddlb_cash (the cash amount given by the customer)
sle_change (the change that the cashier is to give the customer)
the system should set the value for sle_change when the cashier inputs the cash.
1. this gives me syntax error;
if cash=price then
sle_fare.settext=0
end if
2. this gives 'incompatible types in assinment
if cash=price then
sle_fare.text=0
end if
The single line edit (sle) control is designed to hold text. You're trying to assign it a numeric value. You will have to change the number into a string if you want the sle to display it:
sle_fare.text = "0"
or
sle_fare.text = string(variableHere)
Once again, I'm going to step back, ignore the actual questions, and look at how a DataWindow would help as an alternative.
You seem to want a control with a data type behind it. The DataWindow has those types of controls. Don't forget that a DataWindow doesn't have to have a SELECT statement behind it; it can have a stored procedure, web service, or nothing at all (external DataWindow) behind the data set. Once you have a control with a numeric data type behind it, you get (for free) some basic editing controls, such as not allowing alpha characters in the field and making sure the entered value is really a number (e.g. "0-.2.1" would fail).
A step beyond that is looking at one of your coming requirements: calculating change. On a DataWindow, you can create a compute with an expression that will automagically calculate your change for you, once price and cash are entered.
I certainly don't want to say you can't do things the way you're proceeding, but there are many issues that a DataWindow would remove over some other approach. The strength of PowerBuilder is in the DataWindow.
Good luck,
Terry

ReportBuilder 7.x - Controlling Print to File at Print Time

Using ReportBuilder 7.X
Question
Is it possible to Control Print to File.
I need to change the Length of a field at print time
Example:
label2
In the setup - I set its length to 800 which is the max possible this field should ever be.
However, in many cases the record is less than that and i need to set it to the calculated size before printing to file.
Is this possible?
Is it possible to control any portions of this Print to file...at print time (before Print, after print)?
Are the objects avaiable?
We are registered users of the 10.x and above i believe, but have still not gotten around to recompiling are application in Delphi 2009 and the new ReportBuilder....so, that is not an option at this point.
Thanks
Shane
You can try to use the OnDataChange event of the tDataSource that you are using to link your data to your report. This event fires when the current record in the associated dataset changes. In that event, adjust your label to the size for the current record.
i solved this! Each control has a saveLength property. I can just use a global variable that can change at any time (controlling length of entire record). Then just before i print he label, i can set its saveLength property
thanks to all who responded though

Resources