Write a function for each column that accepts an operator as an argument. That way the operators can be supplied via bind variables as well as the operands themselves. This method will probably suffer from performance issues, however, since the optimiser will not be able to calculate the selectivity of the predicates very well at all.
e.g.
FUNCTION company_is (company IN VARCHAR2, op IN VARCHAR2, value IN VARCHAR2) IS
BEGIN
RETURN CASE op
WHEN '=' THEN (company = value)
WHEN 'LIKE' THEN (company LIKE value)
WHEN '<' THEN (company < value)
...
END;
END;
FUNCTION date_is (thedate IN DATE, op IN VARCHAR2, value IN DATE) IS
BEGIN
RETURN CASE op
WHEN '=' THEN (thedate = value)
WHEN '<' THEN (thedate < value)
...
END;
END;
Then you can supply predicates in this way:
SELECT company, accounts
FROM testdrive AS t
WHERE company_is(t.company,'&CompanyOp','&Company')
AND date_is(t.date_created,'&CreatedOp',TO_DATE('&Created','DD/MM/YYYY'))
ORDER BY company DESC
But watch out for the performance issues - unless you can specify some other predicates in the normal way, you're gonna see nothing but full scans!