[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 501
  • Last Modified:

Help using TObject to store integer values

I am trying to change these 3 integers in the following object without having to create a bunch of if...then statements.  Hope you can tell what I am trying to do by the following code snipets.  I just want to be able to get and/or change the value of DTCurrentorder, DWCurrentOrder and MGSCurrentOrder by taking 'CurrentOrder' and putting 'MGS', 'DT', or 'DW' on the beginning.  Hope this makes sense.

Thanks

Rick


type
  TBranchOrder = class(TObject)
    DTCurrentOrder        : integer;
    DWCurrentOrder        : integer;
    MGSCurrentOrder       : integer;
  end;



procedure TfrmPurchaseOrderUpdate.BeginCreateOrders;
var
  BranchOrder: TBranchOrder;
  OrderQty, Avail: integer;
  PartType: String;
  CurrentBuyOutOrder, BuyOutItemNum, CurrentOrder, StockItemNum: ^Integer;
Begin
//intialize all to zero
  BranchOrder.DTCurrentOrder         := 0;
  BranchOrder.DWCurrentOrder         := 0;
  BranchOrder.MGSCurrentOrder        := 0;
  // GetPartType returns either ?MGS?, ?DW?, or ?DT?
  PartType := GetPartType;
  CurrentOrder      := BranchOrder.FieldAddress (PartType+'CurrentOrder');
  if CurrentOrder <> nil then
    CurrentOrder^ := 1;
End;
0
rwhitaker
Asked:
rwhitaker
  • 4
  • 2
  • 2
  • +3
1 Solution
 
kretzschmarCommented:
??? this cannot work

too tired .. . listening . . .
0
 
edeyCommented:
if you include typinfo in your uses clause i would think you'd be able to do something like this:

setInt64Prop(branchOrder,partType+'CurrentOrder',0);

Alt. you could use a a TStringList like so:

branchOrder := TStringList.create;
with branchOrder do
begin
 add('?MGS?');
 add('?DW?');
 add('?DT?');
end;

with branchOrder do
 Integer(objects[indexOf(partType)]) := 0;


Though both are a bit hackish.
GL
Mike
0
 
rwhitakerAuthor Commented:
My bad, The GetPartType function should return either MGS, DW, or DT.  Ignore the question marks.  I don't know where they came from.

Ok, so Let's say GetParts returns the string 'MGS'.  In the object branchorder there is MGSCurrentOrder.   I just want to evaluate the value of BranchOrder.MGSCurrentOrder without having to write something like:

x:=GetPartType;
if x = 'MGS' then
  BranchOrder.MGSCurrentOrder := 1
else if x = 'DW' then
  BranchOrder.DWCurrentOrder := 1
else
  BranchOrder.DTCurrentOrder := 1;

3 items in my object wouldn't be that bad, but I actually have 12 items.  That if statement looks like crap.


0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
ITugayCommented:
Hi rwhitaker,

may be something like this?

  X:=GetPartType;
  case StringCase(X, ['MGS', 'DW', 'DT']) of
    0: MSGCurrentOrder := 1;
    1: DWCurrentOrder := 1;
    2: DTCurrentOrder := 1;
  end;


here is StringCase implementation:

function StringCase(S: String; A: array of String): Integer;
var
  I: Integer;
begin
  I := -1;
  S := AnsiUppercase(S);
  for I := 0 to High(A) do
    if S = AnsiUppercase(A[I]) then
    begin
      Result := I;
      Break;
    end;
end;
0
 
ITugayCommented:
sorry, wrong implementation. Should be:

function StringCase(S: String; A: array of String): Integer;
var
  I: Integer;
begin
  Result := -1; //*****
  S := AnsiUppercase(S);
  for I := 0 to High(A) do
    if S = AnsiUppercase(A[I]) then
    begin
      Result := I;
      Break;
    end;
end;


0
 
FrodoBegginsCommented:
Igor, better use Low(A) instead of 0 in the loop. Looks better :-)

Rgds,
Frodo
0
 
ITugayCommented:
Hi Frodo,
I will :-)
0
 
ITugayCommented:
Hi rwhitaker,

there is another way. You can declare published properties with the names "MGS", "DW", "DT" and then use procedure to set property value by it's name.

  X:=GetPartType;
  SetPropValue(BranchOrder, X, 1);

procedure located in TypInfo unit.

--------
Igor
0
 
scrapdogCommented:
This, in my opinion, we would be the safest way to do it.  You will have to build the if-then construct, but you will only have to do it twice (once for get, once for set):

type
 TBranchOrder = class(TObject)
   DTCurrentOrder        : integer;
   DWCurrentOrder        : integer;
   MGSCurrentOrder       : integer;
 private
    function GetCurrentOrder(s: string): integer;
    procedure SetCurrentOrder(s: string; const Value: integer);
 public
    property CurrentOrder[s :string] :integer read GetCurrentOrder write SetCurrentOrder;
 end;



function TBranchOrder.GetCurrentOrder(s: string): integer;
begin
    if s = 'DT' then
        Result := DTCurrentOrder
    else if s = 'DW' then
        Result := DWCurrentOrder
    else
        Result := MGSCurrentOrder;
end;

procedure TBranchOrder.SetCurrentOrder(s: string; const Value: integer);
begin
    if s = 'DT' then
        DTCurrentOrder := Value
    else if s = 'DW' then
        DWCurrentOrder := Value
    else
        MGSCurrentOrder := Value;
end;


-----------------------------------

Now you can use CurrentOrder as an array that is indexed by strings.  Like this:


procedure TForm1.Button1Click(Sender: TObject);
var
    Test :TBranchOrder;
begin
    Test := TBranchOrder.Create;

    Test.CurrentOrder['DT'] := 10;
    ShowMessage(IntToStr(Test.CurrentOrder['DT']));

    Test.Free;
end;



You can substitute any string expression for the index (such as the result from GetPartType).
0
 
edeyCommented:
In the end run, you have, I think, one of three choices:

1)use RTTI (see my first comment for typinfo.pas ex).
2)wrap the var's in a hash table like object (see the TStringList Example). There a large number of ways to do this.
3)use of some form of "sieve logic", ie the if .. else if or case of constructs.  Again, many similar ways to do this, as various posters to this question have shown.

Each of these have various strengths & weaknesses, ie:

1)RTTI is very flexible, the only requirement is that the data be ref'ed by an object property.  Can be used with any object, with little info needed at design time.  OTOH, it's not particularily fast, and you still have the overhead of a class/object wrapper.
2)Hash Tables, depending on implmentation, can be very fast, can hold any data type, can be very efficient, good for large amounts of data.  OTOH, takes the most work to implement well, requires a fair bit of 'hard coding' - there's a lot that needs to be known at deisgn time.
3)Sieve's are quick, simple, can be easy to read (for small numbers of conditions).  They also tend to produce fast code, esp. if your condition are ordered well (if 'DT' occurs most often, put it first to avoid the logic of the other two). OTOH, they require the most hard coding - you can't easily change the conditions, the number of conditions nor the number/source of the data.

In your particular case, though, I think I would still sugest 3) - the sieve.  However ugly, I just can't see how you'd be better served with the extra work for most iplementations of 1) or 2).

GL
Mike
0
 
rwhitakerAuthor Commented:
Thanks for the multitude of viable solutions guys.  That was awesome.  In the end, I went with something similiar to what scrapdog suggested.

Again thanks for the help.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 2
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now