In the following video, the author takes an existing class and assigns the Single Responsibility Principle to it. He takes a Print Class that has the job of Accessing Data, Formatting, and Printing the report. He breaks up each method to its own class, so he creates a DataAccess class to handle data access, he creates a ReportFormatter class to handle the formatting of the Report, and he creates a ReportPrinter class to handle the printing of the Report. The original Report class is then left with one method, Print() which calls the ReportPrinter's class method Print. DataAccess and ReportFormatter appear to have responsibility, but ReportPrinter relies on DataAcess and ReportFormatter, so doesn't this break the SRP or am I misunderstanding it?
SRP doesn't address dependencies. Breaking the class up into the single-responsibility classes will facilitate breaking those dependencies later. SRP addresses one of the two principles oftem mentioned together: Cohesion and Coupling. SRP is about high cohesion, and the dependencies can be indicative of high coupling. Good designs have high cohesion and low coupling. Sometimes these two principles can be at odds.
Without watching the video, it sounds like a reasonable design. SRP is not broken, as methods dealing with data access do not appear in the ReportPrinter class, only the concept that "I can call something to get the data I want."
You could push it a bit further, and have a coordinator class responsible only for coordinating the activities of the data access class, the formatter class, and the printer class. You could also arrange the objects in different ways, like having the coordinator sends data to the formatter, which sends it to the printer, and the coordinator doesn't (directly) know about the printer.
Something has to know about coordinating the efforts of the narrowly-focused objects. That becomes their responsibility. It's okay to know about the idea or concept of what the other objects will do, so long as you don't know or care how they do it. Thinking of interfaces as "seams of responsibility" is a good start.
It can also be helpful if you think of objects as passing data to each other, rather than "doing" things. So the ReportFormatter returns (or forwards) a new object representing a formatted report, rather than (conceptually) performing objects on an existing report.
The Single Responsibility Principle indicates that a given class should have a single responsibility (or 'reason to change'). It does not, in and of itself, indicate how that responsibility is to be satisfied. Doing so can, and often does, require the cooperation of multiple other classes as collaborators.