separation lines on weekstart when GetHorizAxis.Increment := DateTimeStep[dtOneWeek] - delphi

I use D2007 and Teechart v7.10 standard
I want to show the data per week.
I set
Series1.GetHorizAxis.Increment := DateTimeStep[dtOneWeek];
and
chart1.TopAxis.minimum = //a Monday's date
The problem is that the vertical separation lines and their dates aren't on
Mondays.
Is any way to force these marks to be at the start of week ?
thanks in advance
Using TGantSeries

I've tried with the actual version (v2013.09) and I always get a bottom axis with labels on Mondays using the following simple example:
uses GanttCh;
procedure TForm1.FormCreate(Sender: TObject);
begin
Chart1.View3D:=false;
Chart1.Legend.Visible:=false;
Chart1.AddSeries(TGanttSeries).FillSampleValues;
with Chart1.Axes.Bottom do
begin
LabelsAngle:=90;
Increment:=DateTimeStep[dtOneWeek];
DateTimeFormat:='ddd dd/mm/yyyy';
end;
end;
However, I see in TeeChart v7 the code above shows different weekdays in the labels depending on the values in the series. Then, the only solution I can think on is to use custom labels. Ie:
uses GanttCh;
procedure TForm1.FormCreate(Sender: TObject);
var tmpDate: TDateTime;
begin
Chart1.View3D:=false;
Chart1.Legend.Visible:=false;
Chart1.AddSeries(TGanttSeries).FillSampleValues;
Chart1.MarginBottom:=15;
with Chart1.Axes.Bottom do
begin
LabelsAngle:=90;
//Increment:=DateTimeStep[dtOneWeek]; //this won't take effect with custom labels
DateTimeFormat:='ddd dd/mm/yyyy';
tmpDate:=(Chart1[0] as TGanttSeries).StartValues.MinValue;
while DayOfWeek(tmpDate) <> 2 do
tmpDate:=tmpDate+1;
Items.Clear;
repeat
Items.Add(tmpDate);
tmpDate:=tmpDate+7;
until tmpDate>=(Chart1[0] as TGanttSeries).EndValues.MaxValue;
end;
end;
Note in the solution above there's no antioverlap control for the axis labels

Related

How to get Id values for the adjacent records in TcxGrid (TcxGridDBTableView)

I have DevExpress cxGrid and I would like to get the Ids of the adjacent records. I can use them in the following use case: user deletes focused record and I position the (grid view) cursor on one of the adjacent records (as determined but the current sorting and grouping order of the grid view). Otherwise the position of the grid cursor is poorly determined after removal of the record and after refreshing the grid view.
I have made the following attempts but they are not working - the Id values are junk:
procedure GetAdjacentRecordIds(AView: TcxGridDBTableView; ACdFieldName: string; var APrevId, AId, ANextId: Integer);
var Item: TcxCustomGridTableItem;
RecIdx: Integer;
i, RecCount: Integer;
begin
APrevId:=-1;
AId:=-1;
ANextId:=-1;
if Trim(AIdFieldName)='' then Exit;
if not Assigned(AView) then Exit;
if not Assigned(AView.DataController) then Exit;
Item:=AView.DataController.GetItemByFieldName(UpperCase(AIdFieldName));
if not Assigned(Item) then Exit;
{//First attempt, didn't work, AId was the right one, but APrevId and ANextId were junk
RecIdx:=AView.DataController.FocusedRecordIndex;
AId:=AView.DataController.Values[RecIdx, Item.Index];
APrevId:=AView.DataController.Values[RecIdx-1, Item.Index];
ANextId:=AView.DataController.Values[RecIdx+1, Item.Index];}
//Second attempt, doesn't work, all three Ids are junk
RecIdx:=-1;
RecCount:=AView.ViewData.RecordCount;
for i:=0 to RecCount-1 do begin
if AView.ViewData.Records[i].Focused then begin
RecIdx:=1;
Break;
end;
end;
if RecIdx<0 then Exit;
AId:=AView.ViewData.Records[RecIdx].Values[Item.Index];
if RecIdx>0 then
APrevId:=AView.ViewData.Records[RecIdx-1].Values[Item.Index];
if RecIdx<RecCount then
ANextId:=AView.ViewData.Records[RecIdx+1].Values[Item.Index];
end;
How can I correct this code to get the field values for adjacent records. Or maybe I should use Grid navigator and do prev/next on it, but I would like to find the values in invisible. And DataSet.DisableControls may stop the Grid navigator?
I used the DevExpress knowledgebase to find this answer. You are referencing the internal storage of the grid incorrectly. You can also use dataset.previous and dataset.next to position the record pointer in a bound grid, and simply use dataset.fieldbyname(AidFieldName).AsInteger to retrieve key values.
get-cell-value-by-column-name
procedure TForm1.Button1Click(Sender: TObject);
var
AColumn: TcxGridDBColumn;
I: Integer;
AView: TcxGridDBTableView;
v: Variant;
begin
AView := cxGrid1DBTableView1;
AColumn := TcxGridDBColumn( AView.FindItemByName('cxGrid1DBTableView1Capital'));
if Assigned(AColumn) then
for I := 0 to AView.ViewData.RowCount - 1 do
v := AView.DataController.Values[AView.ViewData.Rows[0].RecordIndex, AColumn.Index];
end;
Use of the navigation functions of DataSet is not the solution, because CxGrid can have completely different sorting order. But DataController navigation is good solution and there is no visual flickering as well. So, the solution is:
RecIdx:=AView.DataController.FocusedRecordIndex;
AId:=AView.DataController.Values[RecIdx, Item.Index];
if not AView.DataController.IsBOF then begin
AView.DataController.GotoPrev;
RecIdx:=AView.DataController.FocusedRecordIndex;
APrevId:=AView.DataController.Values[RecIdx, Item.Index];
AView.DataController.GotoNext;
end;
if not AView.DataController.IsEOF then begin
AView.DataController.GotoNext;
RecIdx:=AView.DataController.FocusedRecordIndex;
ANextId:=AView.DataController.Values[RecIdx, Item.Index];
AView.DataController.GotoPrev;
end;

Delphi-FastReport VCL 5 Conditional highlighting

I've read this manual , and follow it , but the highlighting not working.
What I have?
Create new VCL application.
Drop a TEdit and TButton components in the form (To pass the value).
Drop a TfrxReport on the form.
Open the report in design mode.
Drop a ReportTile band in the report page.
Drop a TfrxMemoView in the ReportTitle band.
Add conditions:
1- Value <= 0 -> Red color
2- Value > 0 -> Green color
The fill color of the memo still Black even the value is >0 or <=0.
The question:
Why this conditions not working? and how can I make the conditions work?
Update:
The value was passed to the TfrxMemoView component as :
procedure TForm1.Button1Click(Sender: TObject);
Var Mem : TfrxMemoView;
begin
Mem := frxReport1.FindObject('Memo1') as TfrxMemoView;
Mem.Text := Edit1.Text;
frxReport1.ShowReport();
end;
None of the rules is applied because the Value property remains NULL. To assign a constant value from Delphi code you can either write a constant expression, for example:
procedure TForm1.Button1Click(Sender: TObject);
var
Memo: TfrxMemoView;
begin
Memo := frxReport1.FindObject('Memo1') as TfrxMemoView;
Memo.Text := Format('[%s]', [Edit1.Text]);
frxReport1.ShowReport;
end;
In the above code I've omitted check if the control was found. And, you need to be careful with the input text. It accepts only floating point values in format that won't collide in decimal separator with separator(s) defined in the ExpressionDelimiters property.
Or simply set the Value property as well:
procedure TForm1.Button1Click(Sender: TObject);
var
Memo: TfrxMemoView;
begin
Memo := frxReport1.FindObject('Memo1') as TfrxMemoView;
Memo.Text := Edit1.Text;
Memo.Value := StrToFloat(Edit1.Text);
frxReport1.ShowReport;
end;
In this one the check if the control was found is missing as well. And the conversion to float is not necessary there. The Value can be just a string convertible to float.

How to make percentage from calculation record divided with summary DBGRID Delphi

I have dbgrid which display column subtotal and column percentage, how to display column percentage from this formula : (subtotal / grandtotal) * 100% ? for detail information please see below picture
I couldnt modify my SQL, because my SQL is very complicated, so i think solution maybe use calculated field, doesnt it? Could someone help me to solve this problem.
Thanks in advanced.
The following assumes that your dataset doesn't actually contain the last row you've shown, the one that contains "111077, 100" - if it does, then the steps I show below to calculate the GrandTotal are unnecessary, and you only need to populate the Percent calculated field, which is trivial.
If your DataSet is a TClientDataSet, you can implement the Percent values quite easily using the
combination of a TAggregateField to represent the GrandTotal and a calculated field to represent each data row's contribution towards the GrandTotal. See code below.
If you are not using a TClientDataSet already then you have several options,
including
If your DataSet is of a type which supports aggregate fields then you can do the equivalent of the code below.
Use your existing DataSet as the dataset source of a TDataSetProvider, and use the TDataSetProvider as the Provider of a TClientDataSet and use the TClientDataSet to supply the data to your grid.
Don't use a TClientDataSet and/or TAggregateField and instead do similar to what is shown below with your existing DataSet, but make the Percent field an fkInternalCalc field if your DataSet type supports it, or an fkCalculated one if not, omit the GrantTotal TAggregateField field and calculate the GrandTotal in code. One way to do this would be to calculate it by a once-only traversal of the dataset (while not DataSet.Eof ...) after you open it.
In the code below, I've created all the fields in code, rather than using the Object Inspector's Fields editor, so you can easily see exactly what are the minimum settings necessary to get a TAggregateField to work.
Note: I could be wrong but don't think you could get a standard TDBGrid to display the final, 100%, row of your screenshot. Somthething similar could be done using the Developer Express TcxGrid, amongst others, but if you need a TDBGrid to do this, you should ask how to in a new question.
Code
TForm1 = class(TForm)
CDS: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
procedure CDSCalcFields(DataSet: TDataSet);
procedure FormCreate(Sender: TObject);
private
CDSID : TIntegerField;
CDSTotal : TCurrencyField;
CDSPercent : TFloatField;
CDSGrandTotal : TAggregateField;
public
procedure SetUp;
end;
[...]
procedure TForm1.SetUp;
var
i : Integer;
begin
CDSID := TIntegerField.Create(Self);
CDSID.FieldName := 'ID';
CDSID.FieldKind := fkData;
CDSID.DataSet := CDS;
CDSTotal := TCurrencyField.Create(Self);
CDSTotal.FieldName := 'Total';
CDSTotal.FieldKind := fkData;
CDSTotal.DataSet := CDS;
CDSPercent := TFloatField.Create(Self);
CDSPercent.FieldName := 'Percent';
CDSPercent.FieldKind := fkInternalCalc;
CDSPercent.DataSet := CDS;
CDSGrandTotal := TAggregateField.Create(Self);
CDSGrandTotal.FieldName := 'GrandTotal';
CDSGrandTotal.FieldKind := fkAggregate;
CDSGrandTotal.Expression := 'Sum(Total)';
CDSGrandTotal.DataSet := CDS;
CDSGrandTotal.Active := True;
CDS.OnCalcFields := CDSCalcFields;
CDS.IndexFieldNames := 'ID';
CDS.CreateDataSet;
for i := 1 to 2 do begin
CDS.InsertRecord([i, i]);
end;
CDS.First;
end;
procedure TForm1.CDSCalcFields(DataSet: TDataSet);
var
Value : Double;
V : Variant;
begin
V := CDSGrandTotal.Value;
if not VarIsNull(V) then begin
Value := CDSTotal.AsFloat;
Value := Value * 100 / V;
CDSPercent.Value := Value;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetUp;
end;

adjusting width of columns in DBGrid [duplicate]

This question already has answers here:
Adjust Column width DBGrid
(6 answers)
Closed 8 years ago.
I am new to delphi :). I have made a simple app that is able to write and read from SQL server database. I am displaying query results in DBGrid.
Currently, I have only 3 columns in my DB (ID, Name, Surname). DBGrid displays them in a waz that I dont like. I can see ID (its width is accurate) and Name, which is stretched all the way to the right, so I have to use horizontal scrollbar to see Surname, which is also extremely wide.
How can I tell DBGrid to adjust width of columns to the widest row?
My app looks like this:
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ADOQuery1.SQL.Text := 'INSERT INTO [dbo].[client] ([Meno],[Priezvisko]) ' +
'VALUES(:Meno, :Priezvisko)';
ADOQuery1.Parameters.ParamByName('Meno').Value := Edit1.Text;
ADOQuery1.Parameters.ParamByName('Priezvisko').Value := Edit2.Text;
ADOQuery1.ExecSQL;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ADOQuery2.SQL.Text := 'SELECT * FROM [dbo].[client] WHERE Meno = :Meno';
ADOQuery2.Active := True;
ADOQuery2.Parameters.ParamByName('Meno').Value := Edit1.Text;
ADOQuery2.ExecSQL;
end;
end.
I have found this TUTORIAL but according to this, you have t double click on chosen coumn to adjust its width, and I had also problems with this line
ColumnWidthHelper.MaxWidth := Max(ColumnWidthHelper.MaxWidth, DBGrid1.Canvas.TextWidth(Column.Field.DisplayText)) ;
It is not recognizing the Max function
Any help would be appreciated :)
The Max function is in the Math unit. Add this to your Uses clause.

write specific line in tmemo according to line number

I am using the following to insert text from a text file into TMemo.
procedure TForm1.Button1Click(Sender: TObject);
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('c:\testimeng\keyfil.txt');
Memo1.Lines.Assign(SL);
finally
SL.Free;
end;
end;
What i want to know is how to add a single line according to row number to TMemo when i choose the specific row number.
Example output:
During this time he has distinguished himself in the academic, sporting and cultural spheres of school life.
During this time he has distinguished himself in the academic and sporting spheres of school life.
During this time he has distinguished himself in the academic and cultural spheres of school life.
During this time he has distinguished himself in the academic aspect of school life.
During this time he has distinguished himself in both the sporting and cultural aspects of school life.
Any help appreciated.
I think you're asking about putting a single line from the TStringList into the TMemo when you specify which item (index, or line number) from the TStringList. If that's the case, you can use something like this:
Memo1.Lines.Add(SL[Index]);
So if the first line in your keyfile.txt is
During this time he has distinguished himself in the academic, sporting and cultural spheres of school life.
You would use
Memo1.Lines.Add(SL[0]); // Desired line number - 1
Ok, after your comment to your question, I think I know what you're wanting to do. Here's one way to do it:
Drop a TListBox, a TButton, and a TMemo on your form. I arranged mine with the ListBox on the left, the button next to it (at the top right corner), and then the memo just to the right of the button.
In the FormCreate event, populate the TListBox with your text file and clear the existing memo content:
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Clear;
ListBox1.Items.LoadFromFile('c:\testimeng\keyfil.txt');
end;
Double-click the button to add an OnClick handler:
procedure TForm1.Button1Click(Sender: TObject);
var
s: string;
begin
// If there's an item selected in the listbox...
if ListBox1.ItemIndex <> -1 then
begin
// Get the selected item
s := ListBox1.Items[ListBox1.ItemIndex];
// See if it's already in the memo. If it's not, add it at the end.
if Memo1.Lines.IndexOf(s) = -1 then
Memo1.Lines.Add(s);
end;
end;
Now run the app. Click on an item in the listbox, and then click the button. If the item is not already present in the memo, it will be added as a new last line. If it's already there, it won't be added (to prevent duplicates).
If you're wanting to add it to the end of the current last line (extending the paragraph, perhaps), then you'd do it like this:
// Add selected sentence to the end of the last line of the memo,
// separating it with a space from the content that's there.
Memo1.Lines[Memo1.Lines.Count - 1] := Memo1.Lines[Memo1.Lines.Count - 1] + #32 + s;
So, it should be clear by now that to add to the end of a specific line, you just grab the content that's already
there and add to it. For instance, if the user types 3 into a TEdit:
procedure TForm1.FormCreate(Sender: TObject);
begin
SL := TStringList.Create;
SL.LoadFromFile('c:\testimeng\keyfil.txt');
end;
procedure TForm1.ButtonAddTextClick(Sender: TObject);
var
TheLine: Integer;
begin
// SL is the TStringList from the FormCreate code above
TheLine := StrToIntDef(Edit1.Text, -1);
if (TheLine > -1) and (TheLine < Memo1.Lines.Count) then
if TheLine < SL.Count then
Memo1.Lines[TheLine] := Memo1.Lines[TheLine] + SL[TheLine];
end;
Write a specific line with String by Mouse Clicking on TMemo
Procedure TForm1.Button1Click(Sender: TObject);
Var SL: TStringList;
LineNumber : Integer;
Begin
LineNumber := Memo1.Perform(EM_LINEFROMCHAR, Memo1.SelStart, 0);
Memo1.SelStart := Memo1.Perform(EM_LINEINDEX, LineNumber, 0);
Memo1.SelLength := Length(Memo1.Lines[LineNumber]) ;
Memo1.SetFocus;
SL := TStringList.Create;
try
SL.LoadFromFile('c:\testimeng\keyfil.txt');
Memo1.SelText := SL.Strings[0];
finally
SL.Free;
end;
End;

Resources