What's the best way to pass a variable/valuable between steps in a SQL Server job For example, if I create a dtsx package that fills out an excel sheet, but only email it out if there is actual data?
The only way to pass state between SQL Server Agent T-SQL Job Steps is via a real, i.e. non-#temp, table, perhaps one that exists only in the tempdb database.  Even a global temp table (##temp) won't suffice since even though it would be accessible to multiple sessions, each T-SQL jobstep runs in it's own session that gets created at the start of the step and ends at the end of the step.  The first session to run would create the ##temp table, but when that step ends, the ##temp table would be destroyed prior to the 2nd step starting.
I'd suggest creating a table in tempdb, in the first step of the job, as in:
USE tempdb;
IF OBJECT_ID(N'dbo.JobStepState', N'U') IS NOT NULL
DROP TABLE dbo.JobStepState;
CREATE TABLE dbo.JobStepState
(
    VariableName varchar(25) NOT NULL
        CONSTRAINT JobStepState_pk
        PRIMARY KEY CLUSTERED
    , VariableValue varchar(25) NOT NULL
);

Then, in a subsequent step you can insert a variable into the table with:
INSERT INTO tempdb.dbo.JobStepState (VariableName, VariableValue)
VALUES ('SomeVariableName', 'SomeValue');

And in later job steps, you can refer to the value using:
DECLARE @val varchar(25);
SET @val = (
    SELECT jss.VariableValue 
    FROM tempdb.dbo.JobStepState jss 
    WHERE jss.VariableName = 'SomeVariableName'
    );
IF @val = 'SomeValue'
    PRINT N'Yes'
ELSE
    PRINT N'No';

DROP TABLE dbo.JobStepState;